19 |
|
import java.util.Arrays; |
20 |
|
import java.util.Collection; |
21 |
|
import java.util.Collections; |
22 |
+ |
import java.util.Comparator; |
23 |
|
import java.util.ConcurrentModificationException; |
24 |
|
import java.util.Iterator; |
25 |
|
import java.util.List; |
30 |
|
import java.util.Spliterators; |
31 |
|
import java.util.concurrent.locks.ReentrantLock; |
32 |
|
import java.util.function.Consumer; |
33 |
< |
import java.util.stream.Stream; |
33 |
> |
import java.util.function.Predicate; |
34 |
> |
import java.util.function.UnaryOperator; |
35 |
|
|
36 |
|
/** |
37 |
|
* A thread-safe variant of {@link java.util.ArrayList} in which all mutative |
111 |
|
* @throws NullPointerException if the specified collection is null |
112 |
|
*/ |
113 |
|
public CopyOnWriteArrayList(Collection<? extends E> c) { |
114 |
< |
Object[] elements = c.toArray(); |
115 |
< |
// c.toArray might (incorrectly) not return Object[] (see 6260652) |
116 |
< |
if (elements.getClass() != Object[].class) |
117 |
< |
elements = Arrays.copyOf(elements, elements.length, Object[].class); |
114 |
> |
Object[] elements; |
115 |
> |
if (c.getClass() == CopyOnWriteArrayList.class) |
116 |
> |
elements = ((CopyOnWriteArrayList<?>)c).getArray(); |
117 |
> |
else { |
118 |
> |
elements = c.toArray(); |
119 |
> |
// c.toArray might (incorrectly) not return Object[] (see 6260652) |
120 |
> |
if (elements.getClass() != Object[].class) |
121 |
> |
elements = Arrays.copyOf(elements, elements.length, Object[].class); |
122 |
> |
} |
123 |
|
setArray(elements); |
124 |
|
} |
125 |
|
|
794 |
|
* @see #add(Object) |
795 |
|
*/ |
796 |
|
public boolean addAll(Collection<? extends E> c) { |
797 |
< |
Object[] cs = c.toArray(); |
797 |
> |
Object[] cs = (c.getClass() == CopyOnWriteArrayList.class) ? |
798 |
> |
((CopyOnWriteArrayList<?>)c).getArray() : c.toArray(); |
799 |
|
if (cs.length == 0) |
800 |
|
return false; |
801 |
|
final ReentrantLock lock = this.lock; |
803 |
|
try { |
804 |
|
Object[] elements = getArray(); |
805 |
|
int len = elements.length; |
806 |
< |
Object[] newElements = Arrays.copyOf(elements, len + cs.length); |
807 |
< |
System.arraycopy(cs, 0, newElements, len, cs.length); |
808 |
< |
setArray(newElements); |
806 |
> |
if (len == 0 && cs.getClass() == Object[].class) |
807 |
> |
setArray(cs); |
808 |
> |
else { |
809 |
> |
Object[] newElements = Arrays.copyOf(elements, len + cs.length); |
810 |
> |
System.arraycopy(cs, 0, newElements, len, cs.length); |
811 |
> |
setArray(newElements); |
812 |
> |
} |
813 |
|
return true; |
814 |
|
} finally { |
815 |
|
lock.unlock(); |
863 |
|
} |
864 |
|
} |
865 |
|
|
866 |
+ |
public void forEach(Consumer<? super E> action) { |
867 |
+ |
if (action == null) throw new NullPointerException(); |
868 |
+ |
Object[] elements = getArray(); |
869 |
+ |
int len = elements.length; |
870 |
+ |
for (int i = 0; i < len; ++i) { |
871 |
+ |
@SuppressWarnings("unchecked") E e = (E) elements[i]; |
872 |
+ |
action.accept(e); |
873 |
+ |
} |
874 |
+ |
} |
875 |
+ |
|
876 |
+ |
public boolean removeIf(Predicate<? super E> filter) { |
877 |
+ |
if (filter == null) throw new NullPointerException(); |
878 |
+ |
final ReentrantLock lock = this.lock; |
879 |
+ |
lock.lock(); |
880 |
+ |
try { |
881 |
+ |
Object[] elements = getArray(); |
882 |
+ |
int len = elements.length; |
883 |
+ |
if (len != 0) { |
884 |
+ |
int newlen = 0; |
885 |
+ |
Object[] temp = new Object[len]; |
886 |
+ |
for (int i = 0; i < len; ++i) { |
887 |
+ |
@SuppressWarnings("unchecked") E e = (E) elements[i]; |
888 |
+ |
if (!filter.test(e)) |
889 |
+ |
temp[newlen++] = e; |
890 |
+ |
} |
891 |
+ |
if (newlen != len) { |
892 |
+ |
setArray(Arrays.copyOf(temp, newlen)); |
893 |
+ |
return true; |
894 |
+ |
} |
895 |
+ |
} |
896 |
+ |
return false; |
897 |
+ |
} finally { |
898 |
+ |
lock.unlock(); |
899 |
+ |
} |
900 |
+ |
} |
901 |
+ |
|
902 |
+ |
public void replaceAll(UnaryOperator<E> operator) { |
903 |
+ |
final ReentrantLock lock = this.lock; |
904 |
+ |
lock.lock(); |
905 |
+ |
try { |
906 |
+ |
Object[] elements = getArray(); |
907 |
+ |
int len = elements.length; |
908 |
+ |
Object[] newElements = Arrays.copyOf(elements, len); |
909 |
+ |
for (int i = 0; i < len; ++i) { |
910 |
+ |
@SuppressWarnings("unchecked") E e = (E) elements[i]; |
911 |
+ |
newElements[i] = operator.apply(e); |
912 |
+ |
} |
913 |
+ |
setArray(newElements); |
914 |
+ |
} finally { |
915 |
+ |
lock.unlock(); |
916 |
+ |
} |
917 |
+ |
} |
918 |
+ |
|
919 |
+ |
public void sort(Comparator<? super E> c) { |
920 |
+ |
final ReentrantLock lock = this.lock; |
921 |
+ |
lock.lock(); |
922 |
+ |
try { |
923 |
+ |
Object[] elements = getArray(); |
924 |
+ |
Object[] newElements = Arrays.copyOf(elements, elements.length); |
925 |
+ |
@SuppressWarnings("unchecked") E[] es = (E[])newElements; |
926 |
+ |
Arrays.sort(es, c); |
927 |
+ |
setArray(newElements); |
928 |
+ |
} finally { |
929 |
+ |
lock.unlock(); |
930 |
+ |
} |
931 |
+ |
} |
932 |
+ |
|
933 |
|
/** |
934 |
|
* Saves this list to a stream (that is, serializes it). |
935 |
|
* |
1358 |
|
} |
1359 |
|
} |
1360 |
|
|
1361 |
+ |
public void forEach(Consumer<? super E> action) { |
1362 |
+ |
if (action == null) throw new NullPointerException(); |
1363 |
+ |
int lo = offset; |
1364 |
+ |
int hi = offset + size; |
1365 |
+ |
Object[] a = expectedArray; |
1366 |
+ |
if (l.getArray() != a) |
1367 |
+ |
throw new ConcurrentModificationException(); |
1368 |
+ |
for (int i = lo; i < hi; ++i) { |
1369 |
+ |
@SuppressWarnings("unchecked") E e = (E) a[i]; |
1370 |
+ |
action.accept(e); |
1371 |
+ |
} |
1372 |
+ |
} |
1373 |
+ |
|
1374 |
|
public Spliterator<E> spliterator() { |
1375 |
|
int lo = offset; |
1376 |
|
int hi = offset + size; |