copyonwritearraylist.java

来自「用applet实现很多应用小程序」· Java 代码 · 共 1,242 行 · 第 1/4 页

JAVA
1,242
字号
            return cursor > 0;
        }

        public Object next() {
            try {
                return (snapshot[cursor++]);
            } catch (IndexOutOfBoundsException ex) {
                throw new NoSuchElementException();
            }
        }

        public Object previous() {
            try {
                return (snapshot[--cursor]);
            } catch (IndexOutOfBoundsException e) {
                throw new NoSuchElementException();
            }
        }

        public int nextIndex() {
            return cursor;
        }

        public int previousIndex() {
            return cursor - 1;
        }

        /**
         * Not supported. Always throws UnsupportedOperationException.
         * @throws UnsupportedOperationException always; <tt>remove</tt>
         *         is not supported by this iterator.
         */
        public void remove() {
            throw new UnsupportedOperationException();
        }

        /**
         * Not supported. Always throws UnsupportedOperationException.
         * @throws UnsupportedOperationException always; <tt>set</tt>
         *         is not supported by this iterator.
         */
        public void set(Object e) {
            throw new UnsupportedOperationException();
        }

        /**
         * Not supported. Always throws UnsupportedOperationException.
         * @throws UnsupportedOperationException always; <tt>add</tt>
         *         is not supported by this iterator.
         */
        public void add(Object e) {
            throw new UnsupportedOperationException();
        }
    }

    /**
     * Returns a view of the portion of this list between
     * <tt>fromIndex</tt>, inclusive, and <tt>toIndex</tt>, exclusive.
     * The returned list is backed by this list, so changes in the
     * returned list are reflected in this list, and vice-versa.
     * While mutative operations are supported, they are probably not
     * very useful for CopyOnWriteArrayLists.
     *
     * <p>The semantics of the list returned by this method become
     * undefined if the backing list (i.e., this list) is
     * <i>structurally modified</i> in any way other than via the
     * returned list.  (Structural modifications are those that change
     * the size of the list, or otherwise perturb it in such a fashion
     * that iterations in progress may yield incorrect results.)
     *
     * @param fromIndex low endpoint (inclusive) of the subList
     * @param toIndex high endpoint (exclusive) of the subList
     * @return a view of the specified range within this list
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public synchronized List subList(int fromIndex, int toIndex) {
        Object[] elements = getArray();
        int len = elements.length;
        if (fromIndex < 0 || toIndex > len  || fromIndex > toIndex)
            throw new IndexOutOfBoundsException();
        return new COWSubList(this, fromIndex, toIndex);
    }


    /**
     * Sublist for CopyOnWriteArrayList.
     * This class extends AbstractList merely for convenience, to
     * avoid having to define addAll, etc. This doesn't hurt, but
     * is wasteful.  This class does not need or use modCount
     * mechanics in AbstractList, but does need to check for
     * concurrent modification using similar mechanics.  On each
     * operation, the array that we expect the backing list to use
     * is checked and updated.  Since we do this for all of the
     * base operations invoked by those defined in AbstractList,
     * all is well.  While inefficient, this is not worth
     * improving.  The kinds of list operations inherited from
     * AbstractList are already so slow on COW sublists that
     * adding a bit more space/time doesn't seem even noticeable.
     */
    private static class COWSubList extends AbstractList {
        private final CopyOnWriteArrayList l;
        private final int offset;
        private int size;
        private Object[] expectedArray;

        // only call this holding l's lock
        private COWSubList(CopyOnWriteArrayList list,
                           int fromIndex, int toIndex) {
            l = list;
            expectedArray = l.getArray();
            offset = fromIndex;
            size = toIndex - fromIndex;
        }

        // only call this holding l's lock
        private void checkForComodification() {
            if (l.getArray() != expectedArray)
                throw new ConcurrentModificationException();
        }

        // only call this holding l's lock
        private void rangeCheck(int index) {
            if (index < 0 || index >= size)
                throw new IndexOutOfBoundsException("Index: " + index +
                                                    ",Size: " + size);
        }

        public Object set(int index, Object element) {
            synchronized (l) {
                rangeCheck(index);
                checkForComodification();
                Object x = l.set(index + offset, element);
                expectedArray = l.getArray();
                return x;
            }
        }

        public Object get(int index) {
            synchronized (l) {
                rangeCheck(index);
                checkForComodification();
                return l.get(index + offset);
            }
        }

        public int size() {
            synchronized (l) {
                checkForComodification();
                return size;
            }
        }

        public void add(int index, Object element) {
            synchronized (l) {
                checkForComodification();
                if (index<0 || index>size)
                    throw new IndexOutOfBoundsException();
                l.add(index + offset, element);
                expectedArray = l.getArray();
                size++;
            }
        }

        public void clear() {
            synchronized (l) {
                checkForComodification();
                l.removeRange(offset, offset+size);
                expectedArray = l.getArray();
                size = 0;
            }
        }

        public Object remove(int index) {
            synchronized (l) {
                rangeCheck(index);
                checkForComodification();
                Object result = l.remove(index + offset);
                expectedArray = l.getArray();
                size--;
                return result;
            }
        }

        public Iterator iterator() {
            synchronized (l) {
                checkForComodification();
                return new COWSubListIterator(l, 0, offset, size);
            }
        }

        public ListIterator listIterator(final int index) {
            synchronized (l) {
                checkForComodification();
                if (index<0 || index>size)
                    throw new IndexOutOfBoundsException("Index: "+index+
                                                        ", Size: "+size);
                return new COWSubListIterator(l, index, offset, size);
            }
        }

        public List subList(int fromIndex, int toIndex) {
            synchronized (l) {
                checkForComodification();
                if (fromIndex<0 || toIndex>size)
                    throw new IndexOutOfBoundsException();
                return new COWSubList(l, fromIndex + offset,
                                         toIndex + offset);
            }
        }

    }


    private static class COWSubListIterator implements ListIterator {
        private final ListIterator i;
        private final int offset;
        private final int size;
        private COWSubListIterator(List l, int index, int offset,
                                   int size) {
            this.offset = offset;
            this.size = size;
            i = l.listIterator(index + offset);
        }

        public boolean hasNext() {
            return nextIndex() < size;
        }

        public Object next() {
            if (hasNext())
                return i.next();
            else
                throw new NoSuchElementException();
        }

        public boolean hasPrevious() {
            return previousIndex() >= 0;
        }

        public Object previous() {
            if (hasPrevious())
                return i.previous();
            else
                throw new NoSuchElementException();
        }

        public int nextIndex() {
            return i.nextIndex() - offset;
        }

        public int previousIndex() {
            return i.previousIndex() - offset;
        }

        public void remove() {
            throw new UnsupportedOperationException();
        }

        public void set(Object e) {
            throw new UnsupportedOperationException();
        }

        public void add(Object e) {
            throw new UnsupportedOperationException();
        }
    }

//    // Support for resetting lock while deserializing
//    private static final Unsafe unsafe =  Unsafe.getUnsafe();
//    private static final long lockOffset;
//    static {
//        try {
//            lockOffset = unsafe.objectFieldOffset
//                (CopyOnWriteArrayList.class.getDeclaredField("lock"));
//            } catch (Exception ex) { throw new Error(ex); }
//    }
//    private void resetLock() {
//        unsafe.putObjectVolatile(this, lockOffset, new ReentrantLock());
//    }
//

    // Temporary emulations of anticipated new j.u.Arrays functions

    private static Object[] copyOfRange(Object[] original, int from, int to,
                                        Class newType) {
        int newLength = to - from;
        if (newLength < 0)
            throw new IllegalArgumentException(from + " > " + to);
        Object[] copy = (Object[]) java.lang.reflect.Array.newInstance
            (newType.getComponentType(), newLength);
        System.arraycopy(original, from, copy, 0,
                         Math.min(original.length - from, newLength));
        return copy;
    }

    private static Object[] copyOf(Object[] original, int newLength,
                                   Class newType) {
        Object[] copy = (Object[]) java.lang.reflect.Array.newInstance
            (newType.getComponentType(), newLength);
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }

    private static Object[] copyOf(Object[] original, int newLength) {
        return copyOf(original, newLength, original.getClass());
    }
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?