437 |
|
} |
438 |
|
|
439 |
|
/** |
440 |
< |
* ConcurrentHashMap list entry. |
440 |
> |
* ConcurrentHashMap list entry. Note that this is never exported |
441 |
> |
* out as a user-visible Map.Entry |
442 |
|
*/ |
443 |
< |
private static class HashEntry<K,V> implements Entry<K,V> { |
443 |
> |
private static class HashEntry<K,V> { |
444 |
|
private final K key; |
445 |
|
private V value; |
446 |
|
private final int hash; |
452 |
|
this.key = key; |
453 |
|
this.next = next; |
454 |
|
} |
454 |
– |
|
455 |
– |
public K getKey() { |
456 |
– |
return key; |
457 |
– |
} |
458 |
– |
|
459 |
– |
public V getValue() { |
460 |
– |
return value; |
461 |
– |
} |
462 |
– |
|
463 |
– |
public V setValue(V newValue) { |
464 |
– |
// We aren't required to, and don't provide any |
465 |
– |
// visibility barriers for setting value. |
466 |
– |
if (newValue == null) |
467 |
– |
throw new NullPointerException(); |
468 |
– |
V oldValue = this.value; |
469 |
– |
this.value = newValue; |
470 |
– |
return oldValue; |
471 |
– |
} |
472 |
– |
|
473 |
– |
public boolean equals(Object o) { |
474 |
– |
if (!(o instanceof Entry)) |
475 |
– |
return false; |
476 |
– |
Entry<K,V> e = (Entry<K,V>)o; |
477 |
– |
return (key.equals(e.getKey()) && value.equals(e.getValue())); |
478 |
– |
} |
479 |
– |
|
480 |
– |
public int hashCode() { |
481 |
– |
return key.hashCode() ^ value.hashCode(); |
482 |
– |
} |
483 |
– |
|
484 |
– |
public String toString() { |
485 |
– |
return key + "=" + value; |
486 |
– |
} |
455 |
|
} |
456 |
|
|
457 |
|
|
920 |
|
private int nextTableIndex; |
921 |
|
private HashEntry[] currentTable; |
922 |
|
private HashEntry<K, V> nextEntry; |
923 |
< |
private HashEntry<K, V> lastReturned; |
923 |
> |
HashEntry<K, V> lastReturned; |
924 |
|
|
925 |
|
private HashIterator() { |
926 |
|
nextSegmentIndex = segments.length - 1; |
981 |
|
public V nextElement() { return super.nextEntry().value; } |
982 |
|
} |
983 |
|
|
984 |
< |
private class EntryIterator extends HashIterator implements Iterator<Entry<K,V>> { |
985 |
< |
public Map.Entry<K,V> next() { return super.nextEntry(); } |
984 |
> |
|
985 |
> |
|
986 |
> |
/** |
987 |
> |
* Exported Entry objects must write-through changes in setValue, |
988 |
> |
* even if the nodes have been cloned. So we cannot return |
989 |
> |
* internal HashEntry objects. Instead, the iterator itself acts |
990 |
> |
* as a forwarding pseudo-entry. |
991 |
> |
*/ |
992 |
> |
private class EntryIterator extends HashIterator implements Map.Entry<K,V>, Iterator<Entry<K,V>> { |
993 |
> |
public Map.Entry<K,V> next() { |
994 |
> |
nextEntry(); |
995 |
> |
return this; |
996 |
> |
} |
997 |
> |
|
998 |
> |
public K getKey() { |
999 |
> |
if (lastReturned == null) |
1000 |
> |
throw new IllegalStateException("Entry was removed"); |
1001 |
> |
return lastReturned.key; |
1002 |
> |
} |
1003 |
> |
|
1004 |
> |
public V getValue() { |
1005 |
> |
if (lastReturned == null) |
1006 |
> |
throw new IllegalStateException("Entry was removed"); |
1007 |
> |
return ConcurrentHashMap.this.get(lastReturned.key); |
1008 |
> |
} |
1009 |
> |
|
1010 |
> |
public V setValue(V value) { |
1011 |
> |
if (lastReturned == null) |
1012 |
> |
throw new IllegalStateException("Entry was removed"); |
1013 |
> |
return ConcurrentHashMap.this.put(lastReturned.key, value); |
1014 |
> |
} |
1015 |
> |
|
1016 |
> |
public boolean equals(Object o) { |
1017 |
> |
if (!(o instanceof Map.Entry)) |
1018 |
> |
return false; |
1019 |
> |
Map.Entry e = (Map.Entry)o; |
1020 |
> |
return eq(getKey(), e.getKey()) && eq(getValue(), e.getValue()); |
1021 |
> |
} |
1022 |
> |
|
1023 |
> |
public int hashCode() { |
1024 |
> |
Object k = getKey(); |
1025 |
> |
Object v = getValue(); |
1026 |
> |
return ((k == null) ? 0 : k.hashCode()) ^ |
1027 |
> |
((v == null) ? 0 : v.hashCode()); |
1028 |
> |
} |
1029 |
> |
|
1030 |
> |
public String toString() { |
1031 |
> |
return getKey() + "=" + getValue(); |
1032 |
> |
} |
1033 |
> |
|
1034 |
> |
private boolean eq(Object o1, Object o2) { |
1035 |
> |
return (o1 == null ? o2 == null : o1.equals(o2)); |
1036 |
> |
} |
1037 |
> |
|
1038 |
|
} |
1039 |
|
|
1040 |
|
private class KeySet extends AbstractSet<K> { |
1093 |
|
public void clear() { |
1094 |
|
ConcurrentHashMap.this.clear(); |
1095 |
|
} |
1096 |
+ |
public Object[] toArray() { |
1097 |
+ |
// Since we don't ordinarily have distinct Entry objects, we |
1098 |
+ |
// must pack elements using exportable SimpleEntry |
1099 |
+ |
Collection<Map.Entry<K,V>> c = new ArrayList<Map.Entry<K,V>>(size()); |
1100 |
+ |
for (Iterator<Map.Entry<K,V>> i = iterator(); i.hasNext(); ) |
1101 |
+ |
c.add(new SimpleEntry<K,V>(i.next())); |
1102 |
+ |
return c.toArray(); |
1103 |
+ |
} |
1104 |
+ |
public <T> T[] toArray(T[] a) { |
1105 |
+ |
Collection<Map.Entry<K,V>> c = new ArrayList<Map.Entry<K,V>>(size()); |
1106 |
+ |
for (Iterator<Map.Entry<K,V>> i = iterator(); i.hasNext(); ) |
1107 |
+ |
c.add(new SimpleEntry<K,V>(i.next())); |
1108 |
+ |
return c.toArray(a); |
1109 |
+ |
} |
1110 |
+ |
|
1111 |
+ |
} |
1112 |
+ |
|
1113 |
+ |
/** |
1114 |
+ |
* This duplicates java.util.AbstractMap.SimpleEntry until this class |
1115 |
+ |
* is made accessible. |
1116 |
+ |
*/ |
1117 |
+ |
static class SimpleEntry<K,V> implements Entry<K,V> { |
1118 |
+ |
K key; |
1119 |
+ |
V value; |
1120 |
+ |
|
1121 |
+ |
public SimpleEntry(K key, V value) { |
1122 |
+ |
this.key = key; |
1123 |
+ |
this.value = value; |
1124 |
+ |
} |
1125 |
+ |
|
1126 |
+ |
public SimpleEntry(Entry<K,V> e) { |
1127 |
+ |
this.key = e.getKey(); |
1128 |
+ |
this.value = e.getValue(); |
1129 |
+ |
} |
1130 |
+ |
|
1131 |
+ |
public K getKey() { |
1132 |
+ |
return key; |
1133 |
+ |
} |
1134 |
+ |
|
1135 |
+ |
public V getValue() { |
1136 |
+ |
return value; |
1137 |
+ |
} |
1138 |
+ |
|
1139 |
+ |
public V setValue(V value) { |
1140 |
+ |
V oldValue = this.value; |
1141 |
+ |
this.value = value; |
1142 |
+ |
return oldValue; |
1143 |
+ |
} |
1144 |
+ |
|
1145 |
+ |
public boolean equals(Object o) { |
1146 |
+ |
if (!(o instanceof Map.Entry)) |
1147 |
+ |
return false; |
1148 |
+ |
Map.Entry e = (Map.Entry)o; |
1149 |
+ |
return eq(key, e.getKey()) && eq(value, e.getValue()); |
1150 |
+ |
} |
1151 |
+ |
|
1152 |
+ |
public int hashCode() { |
1153 |
+ |
return ((key == null) ? 0 : key.hashCode()) ^ |
1154 |
+ |
((value == null) ? 0 : value.hashCode()); |
1155 |
+ |
} |
1156 |
+ |
|
1157 |
+ |
public String toString() { |
1158 |
+ |
return key + "=" + value; |
1159 |
+ |
} |
1160 |
+ |
|
1161 |
+ |
private static boolean eq(Object o1, Object o2) { |
1162 |
+ |
return (o1 == null ? o2 == null : o1.equals(o2)); |
1163 |
+ |
} |
1164 |
|
} |
1165 |
|
|
1166 |
|
/* ---------------- Serialization Support -------------- */ |