Collection细节 一、指定初始容量 二、asList的缺陷 2.1 避免使用基本数据类型数组转换为列表 1 2 3 4 5 6 7 8 public class Test { public static void main (String[] args) { int [] ints = {1 ,2 ,3 ,4 ,5 }; List list = Arrays.asList(ints); System.out.println("list'size:" + list.size()); } } outPut: list'size:1
因为该实例是将int 类型的数组当做其参数,而在Java中数组是一个对象,它是可以泛型化的。所以该例子是不会产生错误的。既然例子是将整个int 类型的数组当做泛型参数,那么经过asList转换就只有一个int 的列表了
1 2 3 4 5 6 7 8 public class Test { public static void main (String[] args) { Integer[] ints = {1 ,2 ,3 ,4 ,5 }; List list = Arrays.asList(ints); System.out.println("list'size:" + list.size()); } } outPut: list'size:5
2.2 asList产生的列表不可操作 1 2 3 4 5 6 7 8 public class Test { public static void main (String[] args) { Integer[] ints = {1 ,2 ,3 ,4 ,5 }; List list = Arrays.asList(ints); list.add(6 ); } }
因为 此 List 是 Arrays的一个内部类,
1 2 3 public static <T> List<T> asList (T... a) { return new ArrayList<>(a); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 java.util.Arrays$ArrayList 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); } @Override public int size () { return a.length; } @Override public Object[] toArray() { return a.clone(); } @Override @SuppressWarnings ("unchecked" ) public <T> T[] toArray(T[] a) { int size = size(); if (a.length < size) return Arrays.copyOf(this .a, size, (Class<? extends T[]>) a.getClass()); System.arraycopy(this .a, 0 , a, 0 , size); if (a.length > size) a[size] = null ; return a; } @Override public E get (int index) { return a[index]; } @Override public E set (int index, E element) { E oldValue = a[index]; a[index] = element; return oldValue; } @Override public int indexOf (Object o) { E[] a = this .a; if (o == null ) { for (int i = 0 ; i < a.length; i++) if (a[i] == null ) return i; } else { for (int i = 0 ; i < a.length; i++) if (o.equals(a[i])) return i; } return -1 ; } @Override public boolean contains (Object o) { return indexOf(o) != -1 ; } @Override public Spliterator<E> spliterator () { return Spliterators.spliterator(a, Spliterator.ORDERED); } @Override public void forEach (Consumer<? super E> action) { Objects.requireNonNull(action); for (E e : a) { action.accept(e); } } @Override public void replaceAll (UnaryOperator<E> operator) { Objects.requireNonNull(operator); E[] a = this .a; for (int i = 0 ; i < a.length; i++) { a[i] = operator.apply(a[i]); } } @Override public void sort (Comparator<? super E> c) { Arrays.sort(a, c); } }
里面并没有 add 方法,所以会报错。
三、subList的缺陷 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class Test { public static void main (String[] args) { List<Integer> list1 = new ArrayList<Integer>(); list1.add(1 ); list1.add(2 ); List<Integer> list2 = new ArrayList<Integer>(list1); List<Integer> list3 = list1.subList(0 , list1.size()); list3.add(3 ); System.out.println("list1 == list2:" + list1.equals(list2)); System.out.println("list1 == list3:" + list1.equals(list3)); } }
3.1 subList返回仅仅只是一个视图 由subList 源码,可以发现问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 public List<E> subList (int fromIndex, int toIndex) { subListRangeCheck(fromIndex, toIndex, size); return new SubList(this , 0 , fromIndex, toIndex); } private class SubList extends AbstractList <E > implements RandomAccess { private final AbstractList<E> parent; private final int parentOffset; private final int offset; int size; SubList(AbstractList<E> parent, int offset, int fromIndex, int toIndex) { this .parent = parent; this .parentOffset = fromIndex; this .offset = offset + fromIndex; this .size = toIndex - fromIndex; this .modCount = ArrayList.this .modCount; } } public void add (int index, E e) { rangeCheckForAdd(index); checkForComodification(); parent.add(parentOffset + index, e); this .modCount = parent.modCount; this .size++; } public E remove (int index) { rangeCheck(index); checkForComodification(); E result = parent.remove(parentOffset + index); this .modCount = parent.modCount; this .size--; return result; }
so,subList返回的只是原列表的一个视图,它所有的操作最终都会作用在原列表上 。
3.2 subList生成子列表后,不要试图去操作原列表 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class Test { public static void main (String[] args) { List<Integer> list1 = new ArrayList<Integer>(); list1.add(1 ); list1.add(2 ); List<Integer> list3 = list1.subList(0 , list1.size()); list1.add(3 ); System.out.println("list1'size: " + list1.size()); System.out.println("list3'size:" + list3.size()); } } private void checkForComodification () { if (ArrayList.this .modCount != this .modCount) throw new ConcurrentModificationException(); }
3.3 推荐使用subList处理局部列表 如 获取一堆数据后,需要删除某段数据。例如,有一个列表存在1000条记录,我们需要删除100-200位置处的数据
1 2 3 4 5 6 7 public void clear () { modCount++; for (int i = 0 ; i < size; i++) elementData[i] = null ; size = 0 ; } list.subList(100 , 200 ).clear();