Java SubList的使用陷阱

代码:

    public static void main(String[] args) {
        List<Integer> list = new ArrayList<Integer>();
        list.addAll(Arrays.asList(1, 4, 2, 5));
        List<Integer> sub = list.subList(1, 3);
        System.out.println("sub: " + sub);
        System.out.println("list: "+list);
        Collections.sort(sub);
        System.out.println("sorted sub: " + sub);
        System.out.println("sorted list: " + list);
    }

输出:

sub: [4, 2]
list: [1, 4, 2, 5]
sorted sub: [2, 4]
sorted list: [1, 2, 4, 5]

解析:

    public List<E> subList(int fromIndex, int toIndex) {
        subListRangeCheck(fromIndex, toIndex, size);
        return new SubList(this, 0, fromIndex, toIndex);
    }

在进行subList()操作时,其实返回的是ArrayList的一个子类叫做SubList的类型

    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;
        }
        ....
    }

发现构造函数中包含指向原本list的引用parent。

        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;
        }

发现此类的修改方法会对parent也进行相关的操作。

    public static <T extends Comparable<? super T>> void sort(List<T> list) {
        Object[] a = list.toArray();
        Arrays.sort(a);
        ListIterator<T> i = list.listIterator();
        for (int j=0; j<a.length; j++) {
            i.next();
            i.set((T)a[j]);
        }
    }

collections.sort()方法得到其一个迭代器:

        public Iterator<E> iterator() {
            return listIterator();
        }
        public void set(E e) {
                    if (lastRet < 0)
                        throw new IllegalStateException();
                    checkForComodification();

                    try {
                        ArrayList.this.set(offset + lastRet, e);
                    } catch (IndexOutOfBoundsException ex) {
                        throw new ConcurrentModificationException();
                    }
       }

会发现迭代器修改了原来的list

你可能感兴趣的:(Java SubList的使用陷阱)