104 |
|
* @see Vector |
105 |
|
* @since 1.2 |
106 |
|
*/ |
107 |
– |
|
107 |
|
public class ArrayList<E> extends AbstractList<E> |
108 |
|
implements List<E>, RandomAccess, Cloneable, java.io.Serializable |
109 |
|
{ |
716 |
|
* @see Collection#contains(Object) |
717 |
|
*/ |
718 |
|
public boolean removeAll(Collection<?> c) { |
720 |
– |
Objects.requireNonNull(c); |
719 |
|
return batchRemove(c, false); |
720 |
|
} |
721 |
|
|
736 |
|
* @see Collection#contains(Object) |
737 |
|
*/ |
738 |
|
public boolean retainAll(Collection<?> c) { |
741 |
– |
Objects.requireNonNull(c); |
739 |
|
return batchRemove(c, true); |
740 |
|
} |
741 |
|
|
742 |
|
private boolean batchRemove(Collection<?> c, boolean complement) { |
743 |
< |
final Object[] elementData = this.elementData; |
744 |
< |
int r = 0, w = 0; |
745 |
< |
boolean modified = false; |
746 |
< |
try { |
747 |
< |
for (; r < size; r++) |
748 |
< |
if (c.contains(elementData[r]) == complement) |
749 |
< |
elementData[w++] = elementData[r]; |
750 |
< |
} finally { |
751 |
< |
// Preserve behavioral compatibility with AbstractCollection, |
752 |
< |
// even if c.contains() throws. |
753 |
< |
if (r != size) { |
754 |
< |
System.arraycopy(elementData, r, |
755 |
< |
elementData, w, |
756 |
< |
size - r); |
743 |
> |
Objects.requireNonNull(c); |
744 |
> |
final Object[] es = elementData; |
745 |
> |
final int size = this.size; |
746 |
> |
final boolean modified; |
747 |
> |
int r; |
748 |
> |
// Optimize for initial run of survivors |
749 |
> |
for (r = 0; r < size && c.contains(es[r]) == complement; r++) |
750 |
> |
; |
751 |
> |
if (modified = (r < size)) { |
752 |
> |
int w = r++; |
753 |
> |
try { |
754 |
> |
for (Object e; r < size; r++) |
755 |
> |
if (c.contains(e = es[r]) == complement) |
756 |
> |
es[w++] = e; |
757 |
> |
} catch (Throwable ex) { |
758 |
> |
// Preserve behavioral compatibility with AbstractCollection, |
759 |
> |
// even if c.contains() throws. |
760 |
> |
System.arraycopy(es, r, es, w, size - r); |
761 |
|
w += size - r; |
762 |
< |
} |
763 |
< |
if (w != size) { |
763 |
< |
// clear to let GC do its work |
764 |
< |
for (int i = w; i < size; i++) |
765 |
< |
elementData[i] = null; |
762 |
> |
throw ex; |
763 |
> |
} finally { |
764 |
|
modCount += size - w; |
765 |
< |
size = w; |
768 |
< |
modified = true; |
765 |
> |
Arrays.fill(es, (this.size = w), size, null); |
766 |
|
} |
767 |
|
} |
768 |
|
return modified; |
1492 |
|
} |
1493 |
|
} |
1494 |
|
|
1495 |
+ |
@SuppressWarnings("unchecked") |
1496 |
|
@Override |
1497 |
|
public boolean removeIf(Predicate<? super E> filter) { |
1498 |
|
Objects.requireNonNull(filter); |
1499 |
< |
final int expectedModCount = modCount; |
1500 |
< |
final Object[] elementData = this.elementData; |
1501 |
< |
int r = 0, w = 0, remaining = size, deleted = 0; |
1502 |
< |
try { |
1503 |
< |
for (; remaining > 0; remaining--, r++) { |
1504 |
< |
@SuppressWarnings("unchecked") E e = (E) elementData[r]; |
1505 |
< |
if (filter.test(e)) |
1506 |
< |
deleted++; |
1507 |
< |
else { |
1508 |
< |
if (r != w) |
1509 |
< |
elementData[w] = e; |
1510 |
< |
w++; |
1511 |
< |
} |
1512 |
< |
} |
1513 |
< |
if (modCount != expectedModCount) |
1514 |
< |
throw new ConcurrentModificationException(); |
1515 |
< |
return deleted > 0; |
1516 |
< |
} catch (Throwable ex) { |
1517 |
< |
for (; remaining > 0; remaining--, r++, w++) |
1518 |
< |
elementData[w] = elementData[r]; |
1519 |
< |
throw ex; |
1520 |
< |
} finally { |
1521 |
< |
if (deleted > 0) { |
1524 |
< |
modCount++; |
1525 |
< |
size -= deleted; |
1526 |
< |
while (--deleted >= 0) |
1527 |
< |
elementData[w++] = null; |
1499 |
> |
int expectedModCount = modCount; |
1500 |
> |
final Object[] es = elementData; |
1501 |
> |
final int size = this.size; |
1502 |
> |
final boolean modified; |
1503 |
> |
int r; |
1504 |
> |
// Optimize for initial run of survivors |
1505 |
> |
for (r = 0; r < size && !filter.test((E) es[r]); r++) |
1506 |
> |
; |
1507 |
> |
if (modified = (r < size)) { |
1508 |
> |
expectedModCount++; |
1509 |
> |
modCount++; |
1510 |
> |
int w = r++; |
1511 |
> |
try { |
1512 |
> |
for (E e; r < size; r++) |
1513 |
> |
if (!filter.test(e = (E) es[r])) |
1514 |
> |
es[w++] = e; |
1515 |
> |
} catch (Throwable ex) { |
1516 |
> |
// copy remaining elements |
1517 |
> |
System.arraycopy(es, r, es, w, size - r); |
1518 |
> |
w += size - r; |
1519 |
> |
throw ex; |
1520 |
> |
} finally { |
1521 |
> |
Arrays.fill(es, (this.size = w), size, null); |
1522 |
|
} |
1523 |
|
} |
1524 |
+ |
if (modCount != expectedModCount) |
1525 |
+ |
throw new ConcurrentModificationException(); |
1526 |
+ |
return modified; |
1527 |
|
} |
1528 |
|
|
1529 |
|
@Override |