716 |
|
* @see Collection#contains(Object) |
717 |
|
*/ |
718 |
|
public boolean removeAll(Collection<?> c) { |
719 |
– |
Objects.requireNonNull(c); |
719 |
|
return batchRemove(c, false); |
720 |
|
} |
721 |
|
|
736 |
|
* @see Collection#contains(Object) |
737 |
|
*/ |
738 |
|
public boolean retainAll(Collection<?> c) { |
740 |
– |
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; r++) |
750 |
> |
if (c.contains(es[r]) != complement) |
751 |
> |
break; |
752 |
> |
if (modified = (r < size)) { |
753 |
> |
int w = r++; |
754 |
> |
try { |
755 |
> |
for (Object e; r < size; r++) |
756 |
> |
if (c.contains(e = es[r]) == complement) |
757 |
> |
es[w++] = e; |
758 |
> |
} catch (Throwable ex) { |
759 |
> |
// Preserve behavioral compatibility with AbstractCollection, |
760 |
> |
// even if c.contains() throws. |
761 |
> |
System.arraycopy(es, r, es, w, size - r); |
762 |
|
w += size - r; |
763 |
< |
} |
764 |
< |
if (w != size) { |
762 |
< |
// clear to let GC do its work |
763 |
< |
for (int i = w; i < size; i++) |
764 |
< |
elementData[i] = null; |
763 |
> |
throw ex; |
764 |
> |
} finally { |
765 |
|
modCount += size - w; |
766 |
< |
size = w; |
767 |
< |
modified = true; |
766 |
> |
Arrays.fill(es, (this.size = w), size, null); |
767 |
|
} |
768 |
|
} |
769 |
|
return modified; |
1502 |
|
final int size = this.size; |
1503 |
|
final boolean modified; |
1504 |
|
int r; |
1505 |
+ |
// Optimize for initial run of survivors |
1506 |
|
for (r = 0; r < size; r++) |
1507 |
|
if (filter.test((E) es[r])) |
1508 |
|
break; |
1514 |
|
for (E e; r < size; r++) |
1515 |
|
if (!filter.test(e = (E) es[r])) |
1516 |
|
es[w++] = e; |
1517 |
– |
Arrays.fill(es, (this.size = w), size, null); |
1517 |
|
} catch (Throwable ex) { |
1518 |
|
// copy remaining elements |
1519 |
|
System.arraycopy(es, r, es, w, size - r); |
1520 |
< |
Arrays.fill(es, (this.size = w + size - r), size, null); |
1520 |
> |
w += size - r; |
1521 |
|
throw ex; |
1522 |
+ |
} finally { |
1523 |
+ |
Arrays.fill(es, (this.size = w), size, null); |
1524 |
|
} |
1525 |
|
} |
1526 |
|
if (modCount != expectedModCount) |