zoukankan      html  css  js  c++  java
  • 使用List需要注意的点

    1. 概述

    在使用List集合时有些地方需要注意一下的, 不然会出现一些莫名其妙的错误.

    2. Arrays.asList();

    2-1. 产生不可操作的集合

    来看一个例子.

    Integer[] array = {1, 2, 3, 4, 5};
    List<Integer> list = Arrays.asList(array);
    list.remove(1);
    

    会直接抛出java.lang.UnsupportedOperationException异常, 为什么呢?

    答案是: 返回的List非java.util.ArrayList. 而是在Arrays类内部有一个静态内部类叫ArrayList.

    静态内部类ArrayList并没有提供所有的方法实现, 有些方法在抽象类中仅仅是一个抛异常的实现, 上述的remove就是这种情况. asList返回的列表只不过是披着list的外衣, 它并没有list的基本特性(变长), 该list是一个长度不可变的列表, 传入参数的数组有多长, 其返回的列表就只能是多长. 所以不要试图改变asList的返回列表.

    Arrays.asList的代码如下:

    public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }
    
    private static class ArrayList<E> extends AbstractList<E>
        implements RandomAccess, java.io.Serializable
    {
        private static final long serialVersionUID = -2764017481108945198L;
        private final E[] a;
    
        ArrayList(E[] array) {
            a = Objects.requireNonNull(array);
        }
    
        // 省略部分源码
    }
    

    该类也是继承了AbstractkList抽象类, 只是该类并没有提供所有方法的实现.

    2-2. 需要传入对象数组而不是基本类型数组

    看个例子:

    int[] array1 = {1, 2, 3, 4, 5};
    List<int[]> list1 = Arrays.asList(array1);
    System.out.println(list1.size()); // 1
    
    Integer[] array2 = {1, 2, 3, 4, 5};
    List<Integer> list2 = Arrays.asList(array2);
    System.out.println(list2.size()); // 5
    

    看到Array.asList的返回值的泛型就明白, list1中存储的实际是一个数组. 为什么这样呢? 数值类型不能被泛型化, 比如List<int>是不对的, 必须是List<Integer>才对.

    3. arrayList.subList();

    3-1. subList返回的并不是ArrayList

    方法返回的是一个内部类SubList, 并不是ArrayList, SubList也是继承AbstractList, 内部引用了原列表的List.

    3-2. subList返回的仅仅是一个视图

    subList返回的仅仅是一个视图, 对subList返回值的所有操作都会作用在原列表中.

    看一个例子

    List<String> list = new ArrayList<>();
    list.add("A");
    list.add("B");
    list.add("C");
    list.add("D");
    list.add("E");
    
    List<String> subList = list.subList(2, 4);
    subList.add("F");
    System.out.println(list); // 输出 [A, B, C, D, F, E]
    

    通过输出结果可知, F被添加到原列表中了.

    3-3. 生成子列表时, 不要试图去操作原列表

    因为子列表是根据原列表动态生成的, 所以如果原列表变了, 那么操作子列表时就会发生ConcurrentModificationException异常. 这个异常的原因相信你也知道, 就是modCount改变了导致的.

    3-4. 推荐使用subList处理局部链表

    比如, 有一个需求要删除列表100-200位置处的数据, 通常我们这样写:

    int start = 100;
    int end = 200;
    for (int i = start; i <= end; i++) {
        list.remove(start);
    }
    

    通过subList, 我们有一个更简洁的处理方式:

    list.subList(100, 200).clear();
    

    简洁.

    不定期更新

    可能还会遇到集合相关的坑.

  • 相关阅读:
    排序-堆排序
    排序-计数排序
    Django之路——10 django的分页组件
    Django之路——9 Django的form组件的信息校验
    Django之路——8 cookie 和sessions
    Django之路——7 django与ajax
    Django之路——6 Django的模型层(二)
    Django之路——6 Django的模型层(一)
    Django之路——4 Django的视图层
    Django之路——5 Django的模板层
  • 原文地址:https://www.cnblogs.com/wuqinglong/p/9760272.html
Copyright © 2011-2022 走看看