244 |
|
* @see #contains(Object) |
245 |
|
*/ |
246 |
|
public boolean containsAll(Collection<?> c) { |
247 |
< |
return al.containsAll(c); |
247 |
> |
return (c instanceof Set) |
248 |
> |
? compareSets(al.getArray(), (Set<?>) c) >= 0 |
249 |
> |
: al.containsAll(c); |
250 |
> |
} |
251 |
> |
|
252 |
> |
/** |
253 |
> |
* Tells whether the objects in snapshot (regarded as a set) are a |
254 |
> |
* superset of the given set. |
255 |
> |
* |
256 |
> |
* @return -1 if snapshot is not a superset, 0 if the two sets |
257 |
> |
* contain precisely the same elements, and 1 if snapshot is a |
258 |
> |
* proper superset of the given set |
259 |
> |
*/ |
260 |
> |
private static int compareSets(Object[] snapshot, Set<?> set) { |
261 |
> |
// Uses O(n^2) algorithm, that is only appropriate for small |
262 |
> |
// sets, which CopyOnWriteArraySets should be. |
263 |
> |
// |
264 |
> |
// Optimize up to O(n) if the two sets share a long common prefix, |
265 |
> |
// as might happen if one set was created as a copy of the other set. |
266 |
> |
|
267 |
> |
final int len = snapshot.length; |
268 |
> |
// Mark matched elements to avoid re-checking |
269 |
> |
final boolean[] matched = new boolean[len]; |
270 |
> |
|
271 |
> |
// j is the largest int with matched[i] true for { i | 0 <= i < j } |
272 |
> |
int j = 0; |
273 |
> |
outer: for (Object x : set) { |
274 |
> |
for (int i = j; i < len; i++) { |
275 |
> |
if (!matched[i] && Objects.equals(x, snapshot[i])) { |
276 |
> |
matched[i] = true; |
277 |
> |
if (i == j) |
278 |
> |
do { j++; } while (j < len && matched[j]); |
279 |
> |
continue outer; |
280 |
> |
} |
281 |
> |
} |
282 |
> |
return -1; |
283 |
> |
} |
284 |
> |
return (j == len) ? 0 : 1; |
285 |
|
} |
286 |
|
|
287 |
|
/** |
373 |
|
* @return {@code true} if the specified object is equal to this set |
374 |
|
*/ |
375 |
|
public boolean equals(Object o) { |
376 |
< |
if (o == this) |
377 |
< |
return true; |
378 |
< |
if (!(o instanceof Set)) |
342 |
< |
return false; |
343 |
< |
Set<?> set = (Set<?>)o; |
344 |
< |
Iterator<?> it = set.iterator(); |
345 |
< |
|
346 |
< |
// Uses O(n^2) algorithm that is only appropriate |
347 |
< |
// for small sets, which CopyOnWriteArraySets should be. |
348 |
< |
|
349 |
< |
// Use a single snapshot of underlying array |
350 |
< |
Object[] elements = al.getArray(); |
351 |
< |
int len = elements.length; |
352 |
< |
// Mark matched elements to avoid re-checking |
353 |
< |
boolean[] matched = new boolean[len]; |
354 |
< |
int k = 0; |
355 |
< |
outer: while (it.hasNext()) { |
356 |
< |
if (++k > len) |
357 |
< |
return false; |
358 |
< |
Object x = it.next(); |
359 |
< |
for (int i = 0; i < len; ++i) { |
360 |
< |
if (!matched[i] && Objects.equals(x, elements[i])) { |
361 |
< |
matched[i] = true; |
362 |
< |
continue outer; |
363 |
< |
} |
364 |
< |
} |
365 |
< |
return false; |
366 |
< |
} |
367 |
< |
return k == len; |
376 |
> |
return (o == this) |
377 |
> |
|| ((o instanceof Set) |
378 |
> |
&& compareSets(al.getArray(), (Set<?>) o) == 0); |
379 |
|
} |
380 |
|
|
381 |
|
public boolean removeIf(Predicate<? super E> filter) { |