2433 |
|
* @return the new set |
2434 |
|
*/ |
2435 |
|
public static <K> KeySetView<K,Boolean> newKeySet() { |
2436 |
< |
return new KeySetView<K,Boolean>(new ConcurrentHashMap<K,Boolean>(), |
2437 |
< |
Boolean.TRUE); |
2436 |
> |
return new KeySetView<K,Boolean> |
2437 |
> |
(new ConcurrentHashMap<K,Boolean>(), Boolean.TRUE); |
2438 |
|
} |
2439 |
|
|
2440 |
|
/** |
2798 |
|
* Returns a {@link Collection} view of the values contained in this map. |
2799 |
|
* The collection is backed by the map, so changes to the map are |
2800 |
|
* reflected in the collection, and vice-versa. |
2801 |
+ |
* |
2802 |
+ |
* @return the collection view |
2803 |
|
*/ |
2804 |
|
public ValuesView<K,V> values() { |
2805 |
|
ValuesView<K,V> vs = values; |
2821 |
|
* and guarantees to traverse elements as they existed upon |
2822 |
|
* construction of the iterator, and may (but is not guaranteed to) |
2823 |
|
* reflect any modifications subsequent to construction. |
2824 |
+ |
* |
2825 |
+ |
* @return the set view |
2826 |
|
*/ |
2827 |
|
public Set<Map.Entry<K,V>> entrySet() { |
2828 |
|
EntrySetView<K,V> es = entrySet; |
4462 |
|
/** |
4463 |
|
* Base class for views. |
4464 |
|
*/ |
4465 |
< |
abstract static class CHMView<K, V> implements java.io.Serializable { |
4465 |
> |
abstract static class CHMCollectionView<K, V, E> |
4466 |
> |
implements Collection<E>, java.io.Serializable { |
4467 |
|
private static final long serialVersionUID = 7249069246763182397L; |
4468 |
|
final ConcurrentHashMap<K, V> map; |
4469 |
< |
CHMView(ConcurrentHashMap<K, V> map) { this.map = map; } |
4469 |
> |
CHMCollectionView(ConcurrentHashMap<K, V> map) { this.map = map; } |
4470 |
|
|
4471 |
|
/** |
4472 |
|
* Returns the map backing this view. |
4475 |
|
*/ |
4476 |
|
public ConcurrentHashMap<K,V> getMap() { return map; } |
4477 |
|
|
4478 |
< |
public final int size() { return map.size(); } |
4479 |
< |
public final boolean isEmpty() { return map.isEmpty(); } |
4480 |
< |
public final void clear() { map.clear(); } |
4478 |
> |
/** |
4479 |
> |
* Removes all of the elements from this view, by removing all |
4480 |
> |
* the mappings from the map backing this view. |
4481 |
> |
*/ |
4482 |
> |
public final void clear() { map.clear(); } |
4483 |
> |
public final int size() { return map.size(); } |
4484 |
> |
public final boolean isEmpty() { return map.isEmpty(); } |
4485 |
|
|
4486 |
|
// implementations below rely on concrete classes supplying these |
4487 |
< |
public abstract Iterator<?> iterator(); |
4487 |
> |
// abstract methods |
4488 |
> |
/** |
4489 |
> |
* Returns a "weakly consistent" iterator that will never |
4490 |
> |
* throw {@link ConcurrentModificationException}, and |
4491 |
> |
* guarantees to traverse elements as they existed upon |
4492 |
> |
* construction of the iterator, and may (but is not |
4493 |
> |
* guaranteed to) reflect any modifications subsequent to |
4494 |
> |
* construction. |
4495 |
> |
*/ |
4496 |
> |
public abstract Iterator<E> iterator(); |
4497 |
|
public abstract boolean contains(Object o); |
4498 |
|
public abstract boolean remove(Object o); |
4499 |
|
|
4501 |
|
|
4502 |
|
public final Object[] toArray() { |
4503 |
|
long sz = map.mappingCount(); |
4504 |
< |
if (sz > (long)(MAX_ARRAY_SIZE)) |
4504 |
> |
if (sz > MAX_ARRAY_SIZE) |
4505 |
|
throw new OutOfMemoryError(oomeMsg); |
4506 |
|
int n = (int)sz; |
4507 |
|
Object[] r = new Object[n]; |
4508 |
|
int i = 0; |
4509 |
< |
Iterator<?> it = iterator(); |
4492 |
< |
while (it.hasNext()) { |
4509 |
> |
for (E e : this) { |
4510 |
|
if (i == n) { |
4511 |
|
if (n >= MAX_ARRAY_SIZE) |
4512 |
|
throw new OutOfMemoryError(oomeMsg); |
4516 |
|
n += (n >>> 1) + 1; |
4517 |
|
r = Arrays.copyOf(r, n); |
4518 |
|
} |
4519 |
< |
r[i++] = it.next(); |
4519 |
> |
r[i++] = e; |
4520 |
|
} |
4521 |
|
return (i == n) ? r : Arrays.copyOf(r, i); |
4522 |
|
} |
4523 |
|
|
4524 |
< |
@SuppressWarnings("unchecked") public final <T> T[] toArray(T[] a) { |
4524 |
> |
@SuppressWarnings("unchecked") |
4525 |
> |
public final <T> T[] toArray(T[] a) { |
4526 |
|
long sz = map.mappingCount(); |
4527 |
< |
if (sz > (long)(MAX_ARRAY_SIZE)) |
4527 |
> |
if (sz > MAX_ARRAY_SIZE) |
4528 |
|
throw new OutOfMemoryError(oomeMsg); |
4529 |
|
int m = (int)sz; |
4530 |
|
T[] r = (a.length >= m) ? a : |
4532 |
|
.newInstance(a.getClass().getComponentType(), m); |
4533 |
|
int n = r.length; |
4534 |
|
int i = 0; |
4535 |
< |
Iterator<?> it = iterator(); |
4518 |
< |
while (it.hasNext()) { |
4535 |
> |
for (E e : this) { |
4536 |
|
if (i == n) { |
4537 |
|
if (n >= MAX_ARRAY_SIZE) |
4538 |
|
throw new OutOfMemoryError(oomeMsg); |
4542 |
|
n += (n >>> 1) + 1; |
4543 |
|
r = Arrays.copyOf(r, n); |
4544 |
|
} |
4545 |
< |
r[i++] = (T)it.next(); |
4545 |
> |
r[i++] = (T)e; |
4546 |
|
} |
4547 |
|
if (a == r && i < n) { |
4548 |
|
r[i] = null; // null-terminate |
4551 |
|
return (i == n) ? r : Arrays.copyOf(r, i); |
4552 |
|
} |
4553 |
|
|
4554 |
< |
public final int hashCode() { |
4555 |
< |
int h = 0; |
4556 |
< |
for (Iterator<?> it = iterator(); it.hasNext();) |
4557 |
< |
h += it.next().hashCode(); |
4558 |
< |
return h; |
4559 |
< |
} |
4560 |
< |
|
4554 |
> |
/** |
4555 |
> |
* Returns a string representation of this collection. |
4556 |
> |
* The string representation consists of the string representations |
4557 |
> |
* of the collection's elements in the order they are returned by |
4558 |
> |
* its iterator, enclosed in square brackets ({@code "[]"}). |
4559 |
> |
* Adjacent elements are separated by the characters {@code ", "} |
4560 |
> |
* (comma and space). Elements are converted to strings as by |
4561 |
> |
* {@link String#valueOf(Object)}. |
4562 |
> |
* |
4563 |
> |
* @return a string representation of this collection |
4564 |
> |
*/ |
4565 |
|
public final String toString() { |
4566 |
|
StringBuilder sb = new StringBuilder(); |
4567 |
|
sb.append('['); |
4568 |
< |
Iterator<?> it = iterator(); |
4568 |
> |
Iterator<E> it = iterator(); |
4569 |
|
if (it.hasNext()) { |
4570 |
|
for (;;) { |
4571 |
|
Object e = it.next(); |
4580 |
|
|
4581 |
|
public final boolean containsAll(Collection<?> c) { |
4582 |
|
if (c != this) { |
4583 |
< |
for (Iterator<?> it = c.iterator(); it.hasNext();) { |
4563 |
< |
Object e = it.next(); |
4583 |
> |
for (Object e : c) { |
4584 |
|
if (e == null || !contains(e)) |
4585 |
|
return false; |
4586 |
|
} |
4590 |
|
|
4591 |
|
public final boolean removeAll(Collection<?> c) { |
4592 |
|
boolean modified = false; |
4593 |
< |
for (Iterator<?> it = iterator(); it.hasNext();) { |
4593 |
> |
for (Iterator<E> it = iterator(); it.hasNext();) { |
4594 |
|
if (c.contains(it.next())) { |
4595 |
|
it.remove(); |
4596 |
|
modified = true; |
4601 |
|
|
4602 |
|
public final boolean retainAll(Collection<?> c) { |
4603 |
|
boolean modified = false; |
4604 |
< |
for (Iterator<?> it = iterator(); it.hasNext();) { |
4604 |
> |
for (Iterator<E> it = iterator(); it.hasNext();) { |
4605 |
|
if (!c.contains(it.next())) { |
4606 |
|
it.remove(); |
4607 |
|
modified = true; |
4612 |
|
|
4613 |
|
} |
4614 |
|
|
4615 |
+ |
abstract static class CHMSetView<K, V, E> |
4616 |
+ |
extends CHMCollectionView<K, V, E> |
4617 |
+ |
implements Set<E>, java.io.Serializable { |
4618 |
+ |
private static final long serialVersionUID = 7249069246763182397L; |
4619 |
+ |
CHMSetView(ConcurrentHashMap<K, V> map) { super(map); } |
4620 |
+ |
|
4621 |
+ |
// Implement Set API |
4622 |
+ |
|
4623 |
+ |
/** |
4624 |
+ |
* Implements {@link Set#hashCode()}. |
4625 |
+ |
* @return the hash code value for this set |
4626 |
+ |
*/ |
4627 |
+ |
public final int hashCode() { |
4628 |
+ |
int h = 0; |
4629 |
+ |
for (E e : this) |
4630 |
+ |
h += e.hashCode(); |
4631 |
+ |
return h; |
4632 |
+ |
} |
4633 |
+ |
|
4634 |
+ |
/** |
4635 |
+ |
* Implements {@link Set#equals(Object)}. |
4636 |
+ |
* @param o object to be compared for equality with this set |
4637 |
+ |
* @return {@code true} if the specified object is equal to this set |
4638 |
+ |
*/ |
4639 |
+ |
public final boolean equals(Object o) { |
4640 |
+ |
Set<?> c; |
4641 |
+ |
return ((o instanceof Set) && |
4642 |
+ |
((c = (Set<?>)o) == this || |
4643 |
+ |
(containsAll(c) && c.containsAll(this)))); |
4644 |
+ |
} |
4645 |
+ |
} |
4646 |
+ |
|
4647 |
|
/** |
4648 |
|
* A view of a ConcurrentHashMap as a {@link Set} of keys, in |
4649 |
|
* which additions may optionally be enabled by mapping to a |
4651 |
|
* {@link #keySet()}, {@link #keySet(Object)}, {@link #newKeySet()}, |
4652 |
|
* {@link #newKeySet(int)}. |
4653 |
|
*/ |
4654 |
< |
public static class KeySetView<K,V> extends CHMView<K,V> |
4655 |
< |
implements Set<K>, java.io.Serializable { |
4654 |
> |
public static class KeySetView<K,V> |
4655 |
> |
extends CHMSetView<K,V,K> |
4656 |
> |
implements Set<K>, java.io.Serializable { |
4657 |
|
private static final long serialVersionUID = 7249069246763182397L; |
4658 |
|
private final V value; |
4659 |
|
KeySetView(ConcurrentHashMap<K, V> map, V value) { // non-public |
4670 |
|
*/ |
4671 |
|
public V getMappedValue() { return value; } |
4672 |
|
|
4673 |
< |
// implement Set API |
4674 |
< |
|
4673 |
> |
/** |
4674 |
> |
* {@inheritDoc} |
4675 |
> |
* @throws NullPointerException if the specified key is null |
4676 |
> |
*/ |
4677 |
|
public boolean contains(Object o) { return map.containsKey(o); } |
4623 |
– |
public boolean remove(Object o) { return map.remove(o) != null; } |
4678 |
|
|
4679 |
|
/** |
4680 |
< |
* Returns a "weakly consistent" iterator that will never |
4681 |
< |
* throw {@link ConcurrentModificationException}, and |
4682 |
< |
* guarantees to traverse elements as they existed upon |
4683 |
< |
* construction of the iterator, and may (but is not |
4684 |
< |
* guaranteed to) reflect any modifications subsequent to |
4685 |
< |
* construction. |
4680 |
> |
* Removes the key from this map view, by removing the key (and its |
4681 |
> |
* corresponding value) from the backing map. This method does |
4682 |
> |
* nothing if the key is not in the map. |
4683 |
> |
* |
4684 |
> |
* @param o the key to be removed from the backing map |
4685 |
> |
* @return {@code true} if the backing map contained the specified key |
4686 |
> |
* @throws NullPointerException if the specified key is null |
4687 |
> |
*/ |
4688 |
> |
public boolean remove(Object o) { return map.remove(o) != null; } |
4689 |
> |
|
4690 |
> |
/** |
4691 |
> |
* @return an iterator over the keys of the backing map |
4692 |
> |
*/ |
4693 |
> |
public Iterator<K> iterator() { return new KeyIterator<K,V>(map); } |
4694 |
> |
|
4695 |
> |
/** |
4696 |
> |
* Adds the specified key to this set view by mapping the key to |
4697 |
> |
* the default mapped value in the backing map, if defined. |
4698 |
|
* |
4699 |
< |
* @return an iterator over the keys of this map |
4699 |
> |
* @param e key to be added |
4700 |
> |
* @return {@code true} if this set changed as a result of the call |
4701 |
> |
* @throws NullPointerException if the specified key is null |
4702 |
> |
* @throws UnsupportedOperationException if no default mapped value |
4703 |
> |
* for additions was provided |
4704 |
|
*/ |
4635 |
– |
public Iterator<K> iterator() { return new KeyIterator<K,V>(map); } |
4705 |
|
public boolean add(K e) { |
4706 |
|
V v; |
4707 |
|
if ((v = value) == null) |
4708 |
|
throw new UnsupportedOperationException(); |
4709 |
|
return map.internalPut(e, v, true) == null; |
4710 |
|
} |
4711 |
+ |
|
4712 |
+ |
/** |
4713 |
+ |
* Adds all of the elements in the specified collection to this set, |
4714 |
+ |
* as if by calling {@link #add} on each one. |
4715 |
+ |
* |
4716 |
+ |
* @param c the elements to be inserted into this set |
4717 |
+ |
* @return {@code true} if this set changed as a result of the call |
4718 |
+ |
* @throws NullPointerException if the collection or any of its |
4719 |
+ |
* elements are {@code null} |
4720 |
+ |
* @throws UnsupportedOperationException if no default mapped value |
4721 |
+ |
* for additions was provided |
4722 |
+ |
*/ |
4723 |
|
public boolean addAll(Collection<? extends K> c) { |
4724 |
|
boolean added = false; |
4725 |
|
V v; |
4731 |
|
} |
4732 |
|
return added; |
4733 |
|
} |
4653 |
– |
public boolean equals(Object o) { |
4654 |
– |
Set<?> c; |
4655 |
– |
return ((o instanceof Set) && |
4656 |
– |
((c = (Set<?>)o) == this || |
4657 |
– |
(containsAll(c) && c.containsAll(this)))); |
4658 |
– |
} |
4734 |
|
|
4735 |
|
public Stream<K> stream() { |
4736 |
|
return Streams.stream(() -> new KeyIterator<K,V>(map), 0); |
4752 |
|
* construction of the iterator, and may (but is not guaranteed to) |
4753 |
|
* reflect any modifications subsequent to construction. |
4754 |
|
*/ |
4755 |
< |
public static final class ValuesView<K,V> extends CHMView<K,V> |
4756 |
< |
implements Collection<V> { |
4755 |
> |
public static final class ValuesView<K,V> |
4756 |
> |
extends CHMCollectionView<K,V,V> |
4757 |
> |
implements Collection<V>, java.io.Serializable { |
4758 |
|
private static final long serialVersionUID = 2249069246763182397L; |
4759 |
< |
ValuesView(ConcurrentHashMap<K, V> map) { super(map); } |
4760 |
< |
public final boolean contains(Object o) { return map.containsValue(o); } |
4759 |
> |
ValuesView(ConcurrentHashMap<K, V> map) { super(map); } |
4760 |
> |
public final boolean contains(Object o) { |
4761 |
> |
return map.containsValue(o); |
4762 |
> |
} |
4763 |
|
public final boolean remove(Object o) { |
4764 |
|
if (o != null) { |
4765 |
< |
Iterator<V> it = new ValueIterator<K,V>(map); |
4688 |
< |
while (it.hasNext()) { |
4765 |
> |
for (Iterator<V> it = iterator(); it.hasNext();) { |
4766 |
|
if (o.equals(it.next())) { |
4767 |
|
it.remove(); |
4768 |
|
return true; |
4773 |
|
} |
4774 |
|
|
4775 |
|
/** |
4776 |
< |
* Returns a "weakly consistent" iterator that will never |
4700 |
< |
* throw {@link ConcurrentModificationException}, and |
4701 |
< |
* guarantees to traverse elements as they existed upon |
4702 |
< |
* construction of the iterator, and may (but is not |
4703 |
< |
* guaranteed to) reflect any modifications subsequent to |
4704 |
< |
* construction. |
4705 |
< |
* |
4706 |
< |
* @return an iterator over the values of this map |
4776 |
> |
* @return an iterator over the values of the backing map |
4777 |
|
*/ |
4778 |
|
public final Iterator<V> iterator() { |
4779 |
|
return new ValueIterator<K,V>(map); |
4780 |
|
} |
4781 |
+ |
|
4782 |
+ |
/** Always throws {@link UnsupportedOperationException}. */ |
4783 |
|
public final boolean add(V e) { |
4784 |
|
throw new UnsupportedOperationException(); |
4785 |
|
} |
4786 |
+ |
/** Always throws {@link UnsupportedOperationException}. */ |
4787 |
|
public final boolean addAll(Collection<? extends V> c) { |
4788 |
|
throw new UnsupportedOperationException(); |
4789 |
|
} |
4804 |
|
* entries. This class cannot be directly instantiated. See |
4805 |
|
* {@link #entrySet()}. |
4806 |
|
*/ |
4807 |
< |
public static final class EntrySetView<K,V> extends CHMView<K,V> |
4808 |
< |
implements Set<Map.Entry<K,V>> { |
4807 |
> |
public static final class EntrySetView<K,V> |
4808 |
> |
extends CHMSetView<K,V,Map.Entry<K,V>> |
4809 |
> |
implements Set<Map.Entry<K,V>>, java.io.Serializable { |
4810 |
|
private static final long serialVersionUID = 2249069246763182397L; |
4811 |
|
EntrySetView(ConcurrentHashMap<K, V> map) { super(map); } |
4812 |
+ |
|
4813 |
|
public final boolean contains(Object o) { |
4814 |
|
Object k, v, r; Map.Entry<?,?> e; |
4815 |
|
return ((o instanceof Map.Entry) && |
4827 |
|
} |
4828 |
|
|
4829 |
|
/** |
4830 |
< |
* Returns a "weakly consistent" iterator that will never |
4756 |
< |
* throw {@link ConcurrentModificationException}, and |
4757 |
< |
* guarantees to traverse elements as they existed upon |
4758 |
< |
* construction of the iterator, and may (but is not |
4759 |
< |
* guaranteed to) reflect any modifications subsequent to |
4760 |
< |
* construction. |
4761 |
< |
* |
4762 |
< |
* @return an iterator over the entries of this map |
4830 |
> |
* @return an iterator over the entries of the backing map |
4831 |
|
*/ |
4832 |
|
public final Iterator<Map.Entry<K,V>> iterator() { |
4833 |
|
return new EntryIterator<K,V>(map); |
4834 |
|
} |
4835 |
|
|
4836 |
+ |
/** |
4837 |
+ |
* Adds the specified mapping to this view. |
4838 |
+ |
* |
4839 |
+ |
* @param e mapping to be added |
4840 |
+ |
* @return {@code true} if this set changed as a result of the call |
4841 |
+ |
* @throws NullPointerException if the entry, its key, or its |
4842 |
+ |
* value is null |
4843 |
+ |
*/ |
4844 |
|
public final boolean add(Entry<K,V> e) { |
4845 |
|
return map.internalPut(e.getKey(), e.getValue(), false) == null; |
4846 |
|
} |
4847 |
+ |
/** |
4848 |
+ |
* Adds all of the mappings in the specified collection to this |
4849 |
+ |
* set, as if by calling {@link #add(Map.Entry)} on each one. |
4850 |
+ |
* @param c the mappings to be inserted into this set |
4851 |
+ |
* @return {@code true} if this set changed as a result of the call |
4852 |
+ |
* @throws NullPointerException if the collection or any of its |
4853 |
+ |
* entries, keys, or values are null |
4854 |
+ |
*/ |
4855 |
|
public final boolean addAll(Collection<? extends Entry<K,V>> c) { |
4856 |
|
boolean added = false; |
4857 |
|
for (Entry<K,V> e : c) { |
4860 |
|
} |
4861 |
|
return added; |
4862 |
|
} |
4779 |
– |
public boolean equals(Object o) { |
4780 |
– |
Set<?> c; |
4781 |
– |
return ((o instanceof Set) && |
4782 |
– |
((c = (Set<?>)o) == this || |
4783 |
– |
(containsAll(c) && c.containsAll(this)))); |
4784 |
– |
} |
4863 |
|
|
4864 |
|
public Stream<Map.Entry<K,V>> stream() { |
4865 |
|
return Streams.stream(() -> new EntryIterator<K,V>(map), 0); |