src/share/classes/java/util/concurrent/CopyOnWriteArrayList.java

Print this page
rev 6197 : [mq]: collections

*** 34,43 **** --- 34,46 ---- */ package java.util.concurrent; import java.util.*; import java.util.concurrent.locks.ReentrantLock; + import java.util.function.Block; + import java.util.function.Predicate; + import java.util.function.UnaryOperator; /** * A thread-safe variant of {@link java.util.ArrayList} in which all mutative * operations (<tt>add</tt>, <tt>set</tt>, and so on) are implemented by * making a fresh copy of the underlying array.
*** 1315,1324 **** --- 1318,1413 ---- public void add(E e) { throw new UnsupportedOperationException(); } } + @SuppressWarnings("unchecked") + public void forEach(Block<? super E> block) { + Objects.requireNonNull(block); + final Object[] elements = getArray(); + for (final Object element : elements) { + block.accept((E) element); + } + } + + @Override + public void sort(Comparator<? super E> c) { + Objects.requireNonNull(c); + final ReentrantLock lock = this.lock; + lock.lock(); + try { + @SuppressWarnings("unchecked") + final E[] elements = (E[]) getArray(); + final E[] newElements = Arrays.copyOf(elements, elements.length); + Arrays.sort(newElements, c); + setArray(newElements); + } finally { + lock.unlock(); + } + } + + @Override + public boolean removeAll(Predicate<? super E> filter) { + Objects.requireNonNull(filter); + final ReentrantLock lock = this.lock; + lock.lock(); + try { + @SuppressWarnings("unchecked") + final E[] elements = (E[]) getArray(); + final int size = elements.length; + + // figure out which elements are to be removed + // any exception thrown from the filter predicate at this stage + // will leave the collection unmodified + int removeCount = 0; + final BitSet removeSet = new BitSet(size); + for (int i=0; i < size; i++) { + final E element = elements[i]; + if (filter.test(element)) { + removeSet.set(i); + removeCount++; + } + } + + // copy surviving elements into a new array + final boolean anyToRemove = removeCount > 0; + if (anyToRemove) { + final int newSize = size - removeCount; + final Object[] newElements = new Object[newSize]; + for (int i=0, j=0; (i < size) && (j < newSize); i++, j++) { + i = removeSet.nextClearBit(i); + newElements[j] = elements[i]; + } + setArray(newElements); + } + + return anyToRemove; + } finally { + lock.unlock(); + } + } + + @Override + public void replaceAll(UnaryOperator<E> operator) { + Objects.requireNonNull(operator); + final ReentrantLock lock = this.lock; + lock.lock(); + try { + @SuppressWarnings("unchecked") + final E[] elements = (E[]) getArray(); + final int len = elements.length; + @SuppressWarnings("unchecked") + final E[] newElements = (E[]) new Object[len]; + for (int i=0; i < len; i++) { + newElements[i] = operator.operate(elements[i]); + } + setArray(newElements); + } finally { + lock.unlock(); + } + } + // Support for resetting lock while deserializing private void resetLock() { UNSAFE.putObjectVolatile(this, lockOffset, new ReentrantLock()); } private static final sun.misc.Unsafe UNSAFE;