10

    技术2026-08-31  26

    Arrays.asList把数据转换为List的三个坑

    1, 不能直接使用Arrays.asList来转换基本类型数
    这个List包含的其实是一个int数组,整个List的元素个数是元素类型是整数数组。 int[] arr = {1, 2, 3}; List list = Arrays.asList(arr); // idea中显示 List<int[]> ints = Arrays.asList(arr); # 修改 使用包装类型 Integer[] array = new Integer[]{1,2}; List<Integer> integers = Arrays.asList(array);
    2, Arrays.asList返回的List**不支持增删操作**
    ,Arrays.asList返回的List并不是我们期望的java.util.ArrayList,**而是Arrays的内部类ArrayList**。ArrayList内部类继承自AbstractList类,并没有覆写父类的add方法,而父类中add方法的实现,就是抛出UnsupportedOperationException。

    优化: 声明一个新的List

    String[] arr = {"1", "2", "3"}; List list = new ArrayList(Arrays.asList(arr));
    3, 使用List.subList进行切片操作居然会导致OOM?
    List<Integer> list = IntStream.rangeClosed(1, 10).boxed().collect(Collectors.toList()); List<Integer> subList = list.subList(1, 4);

    ArrayList的subList 在list有个内部类, 这个sublist没有创建新的list, 直接用的list。 所以修改sublist和list会相互影响。

    解决方法: 1, 不直接使用subList方法返回的SubList,而是重新使用new ArrayList,在构造方法传入SubList,来构建一个独立的ArrayList; 2, 对于Java 8使用Stream的skip和limit API来跳过流中的元素,以及限制流中元素的个数,同样可以达到SubList切片的目的

    //方式一: List<Integer> subList = new ArrayList<>(list.subList(1, 4)); //方式二: List<Integer> subList = list.stream().skip(1).limit(3).collect(Collectors.toList());

    4,asList 数组与返回的list共享数据
    Integer[] integers = new Integer[3]; integers[0] = 1; integers[1] = 2; List<Integer> integers1 = Arrays.asList(integers); integers[2] = 3 ; Arrays.stream(integers).forEach(System.out::println); System.out.println("======>>>>>>"); integers1.forEach(System.out::println);

    一定要让合适的数据结构做合适的事情

    ArrayList和HashMap查找对比

    要对大List进行单值搜索的话,可以考虑 使用HashMap,其中Key是要搜索的值,Value是原始对象,会比使用ArrayList有非常明显的性能优势。ArrayList在内存占用上性价比很高,77%(大约)是实际的数据,而HashMap的“含金量”只有22%(大约)。

    LinkedList和ArrayList插入和查询对比

    书本上的解释:

    对于数组,随机元素访问的时间复杂度是O(1),元素插入操作是O(n); 查询快 对于链表,随机元素访问的时间复杂度是O(n),元素插入操作是O(1)。 插入快

    实际: 数组和链表 查询和插入都比链表快。

    插入操作的时间复杂度是O(1)的前提是,你已经有了那个要插入节点的指针。但,在实现的时候,我们需要先通过循环获取到那个节点的Node,然后再执行插入操作。前者也是有开销的,不可能只考虑插入操作本身的代价: 总结: 1, Arrays.asList得到的是Arrays的内部类ArrayList,List.subList得到的是ArrayList的内部类SubList,不能把这两个内部类转换为ArrayList使用。 2, Arrays.asList直接使用了原始数组,可以认为是共享“存储”,而且不支持增删元素;List.subList直接引用了原始的List,也可以认为是共享“存储”,而且对原始List直接进行结构性修改会导致SubList出现异常。 3, 对Arrays.asList和List.subList容易忽略的是,新的List持有了原始数据的引用,可能会导致原始数据也无法GC的问题,最终导致OOM

    问题:

    调用类型是Integer的ArrayList的remove方法删除元素,传入一个Integer包装类的数字和传入一个int基本类型的数字,结果一样吗?循环遍历List,调用remove方法删除元素,往往会遇到ConcurrentModificationException异常,原因是什么,修复方式又是什么呢?

    1、使用 ArrayList 的 remove方法,如果传参是 Integer类型的话,表示的是删除元素,如果传参是int类型的话,表示的是删除相对应索引位置的元素。;两个都需要进行数组拷贝,是通过System.arraycopy进行的 2、以foreach为例说,遍历删除实质是变化为迭代器实现,不管是迭代器里面的remove()还是next()方法,都会checkForComodification();而这个方法是判断modCount和expectedModCount是否相等,这个modCount是这个list集合修改的次数,每一次add或者remove都会增加这个变量,然后迭代器每次去next或者去remove的时候检查checkForComodification();发现expectedModCount(这个迭代器修改的次数)和modCount(这个集合实际修改的次数)不相等,就会抛出ConcurrentModificationException,迭代器里面没有add方法,用迭代器时,可以删除原来集合的元素,但是!一定要 用迭代器的remove方法而不是集合自身的remove方法,否则抛异常。

    Processed: 0.008, SQL: 9