992 } |
1002 } |
993 |
1003 |
994 public <T> T[] toArray(T[] a) { |
1004 public <T> T[] toArray(T[] a) { |
995 return deepCopy().toArray(a); |
1005 return deepCopy().toArray(a); |
996 } |
1006 } |
997 } |
1007 |
|
1008 public Spliterator<Map.Entry<K,V>> spliterator() { |
|
1009 return new EntrySpliterator<>(WeakHashMap.this, 0, -1, 0, 0); |
|
1010 } |
|
1011 } |
|
1012 |
|
1013 /** |
|
1014 * Similar form as other hash Spliterators, but skips dead |
|
1015 * elements. |
|
1016 */ |
|
1017 static class WeakHashMapSpliterator<K,V> { |
|
1018 final WeakHashMap<K,V> map; |
|
1019 WeakHashMap.Entry<K,V> current; // current node |
|
1020 int index; // current index, modified on advance/split |
|
1021 int fence; // -1 until first use; then one past last index |
|
1022 int est; // size estimate |
|
1023 int expectedModCount; // for comodification checks |
|
1024 |
|
1025 WeakHashMapSpliterator(WeakHashMap<K,V> m, int origin, |
|
1026 int fence, int est, |
|
1027 int expectedModCount) { |
|
1028 this.map = m; |
|
1029 this.index = origin; |
|
1030 this.fence = fence; |
|
1031 this.est = est; |
|
1032 this.expectedModCount = expectedModCount; |
|
1033 } |
|
1034 |
|
1035 final int getFence() { // initialize fence and size on first use |
|
1036 int hi; |
|
1037 if ((hi = fence) < 0) { |
|
1038 WeakHashMap<K,V> m = map; |
|
1039 est = m.size(); |
|
1040 expectedModCount = m.modCount; |
|
1041 hi = fence = m.table.length; |
|
1042 } |
|
1043 return hi; |
|
1044 } |
|
1045 |
|
1046 public final long estimateSize() { |
|
1047 getFence(); // force init |
|
1048 return (long) est; |
|
1049 } |
|
1050 } |
|
1051 |
|
1052 static final class KeySpliterator<K,V> |
|
1053 extends WeakHashMapSpliterator<K,V> |
|
1054 implements Spliterator<K> { |
|
1055 KeySpliterator(WeakHashMap<K,V> m, int origin, int fence, int est, |
|
1056 int expectedModCount) { |
|
1057 super(m, origin, fence, est, expectedModCount); |
|
1058 } |
|
1059 |
|
1060 public KeySpliterator<K,V> trySplit() { |
|
1061 int hi = getFence(), lo = index, mid = (lo + hi) >>> 1; |
|
1062 return (lo >= mid) ? null : |
|
1063 new KeySpliterator<K,V>(map, lo, index = mid, est >>>= 1, |
|
1064 expectedModCount); |
|
1065 } |
|
1066 |
|
1067 public void forEachRemaining(Consumer<? super K> action) { |
|
1068 int i, hi, mc; |
|
1069 if (action == null) |
|
1070 throw new NullPointerException(); |
|
1071 WeakHashMap<K,V> m = map; |
|
1072 WeakHashMap.Entry<K,V>[] tab = m.table; |
|
1073 if ((hi = fence) < 0) { |
|
1074 mc = expectedModCount = m.modCount; |
|
1075 hi = fence = tab.length; |
|
1076 } |
|
1077 else |
|
1078 mc = expectedModCount; |
|
1079 if (tab.length >= hi && (i = index) >= 0 && i < hi) { |
|
1080 index = hi; |
|
1081 WeakHashMap.Entry<K,V> p = current; |
|
1082 do { |
|
1083 if (p == null) |
|
1084 p = tab[i++]; |
|
1085 else { |
|
1086 Object x = p.get(); |
|
1087 p = p.next; |
|
1088 if (x != null) { |
|
1089 @SuppressWarnings("unchecked") K k = |
|
1090 (K) WeakHashMap.unmaskNull(x); |
|
1091 action.accept(k); |
|
1092 } |
|
1093 } |
|
1094 } while (p != null || i < hi); |
|
1095 } |
|
1096 if (m.modCount != mc) |
|
1097 throw new ConcurrentModificationException(); |
|
1098 } |
|
1099 |
|
1100 public boolean tryAdvance(Consumer<? super K> action) { |
|
1101 int hi; |
|
1102 if (action == null) |
|
1103 throw new NullPointerException(); |
|
1104 WeakHashMap.Entry<K,V>[] tab = map.table; |
|
1105 if (tab.length >= (hi = getFence()) && index >= 0) { |
|
1106 while (current != null || index < hi) { |
|
1107 if (current == null) |
|
1108 current = tab[index++]; |
|
1109 else { |
|
1110 Object x = current.get(); |
|
1111 current = current.next; |
|
1112 if (x != null) { |
|
1113 @SuppressWarnings("unchecked") K k = |
|
1114 (K) WeakHashMap.unmaskNull(x); |
|
1115 action.accept(k); |
|
1116 if (map.modCount != expectedModCount) |
|
1117 throw new ConcurrentModificationException(); |
|
1118 return true; |
|
1119 } |
|
1120 } |
|
1121 } |
|
1122 } |
|
1123 return false; |
|
1124 } |
|
1125 |
|
1126 public int characteristics() { |
|
1127 return Spliterator.DISTINCT; |
|
1128 } |
|
1129 } |
|
1130 |
|
1131 static final class ValueSpliterator<K,V> |
|
1132 extends WeakHashMapSpliterator<K,V> |
|
1133 implements Spliterator<V> { |
|
1134 ValueSpliterator(WeakHashMap<K,V> m, int origin, int fence, int est, |
|
1135 int expectedModCount) { |
|
1136 super(m, origin, fence, est, expectedModCount); |
|
1137 } |
|
1138 |
|
1139 public ValueSpliterator<K,V> trySplit() { |
|
1140 int hi = getFence(), lo = index, mid = (lo + hi) >>> 1; |
|
1141 return (lo >= mid) ? null : |
|
1142 new ValueSpliterator<K,V>(map, lo, index = mid, est >>>= 1, |
|
1143 expectedModCount); |
|
1144 } |
|
1145 |
|
1146 public void forEachRemaining(Consumer<? super V> action) { |
|
1147 int i, hi, mc; |
|
1148 if (action == null) |
|
1149 throw new NullPointerException(); |
|
1150 WeakHashMap<K,V> m = map; |
|
1151 WeakHashMap.Entry<K,V>[] tab = m.table; |
|
1152 if ((hi = fence) < 0) { |
|
1153 mc = expectedModCount = m.modCount; |
|
1154 hi = fence = tab.length; |
|
1155 } |
|
1156 else |
|
1157 mc = expectedModCount; |
|
1158 if (tab.length >= hi && (i = index) >= 0 && i < hi) { |
|
1159 index = hi; |
|
1160 WeakHashMap.Entry<K,V> p = current; |
|
1161 do { |
|
1162 if (p == null) |
|
1163 p = tab[i++]; |
|
1164 else { |
|
1165 Object x = p.get(); |
|
1166 V v = p.value; |
|
1167 p = p.next; |
|
1168 if (x != null) |
|
1169 action.accept(v); |
|
1170 } |
|
1171 } while (p != null || i < hi); |
|
1172 } |
|
1173 if (m.modCount != mc) |
|
1174 throw new ConcurrentModificationException(); |
|
1175 } |
|
1176 |
|
1177 public boolean tryAdvance(Consumer<? super V> action) { |
|
1178 int hi; |
|
1179 if (action == null) |
|
1180 throw new NullPointerException(); |
|
1181 WeakHashMap.Entry<K,V>[] tab = map.table; |
|
1182 if (tab.length >= (hi = getFence()) && index >= 0) { |
|
1183 while (current != null || index < hi) { |
|
1184 if (current == null) |
|
1185 current = tab[index++]; |
|
1186 else { |
|
1187 Object x = current.get(); |
|
1188 V v = current.value; |
|
1189 current = current.next; |
|
1190 if (x != null) { |
|
1191 action.accept(v); |
|
1192 if (map.modCount != expectedModCount) |
|
1193 throw new ConcurrentModificationException(); |
|
1194 return true; |
|
1195 } |
|
1196 } |
|
1197 } |
|
1198 } |
|
1199 return false; |
|
1200 } |
|
1201 |
|
1202 public int characteristics() { |
|
1203 return 0; |
|
1204 } |
|
1205 } |
|
1206 |
|
1207 static final class EntrySpliterator<K,V> |
|
1208 extends WeakHashMapSpliterator<K,V> |
|
1209 implements Spliterator<Map.Entry<K,V>> { |
|
1210 EntrySpliterator(WeakHashMap<K,V> m, int origin, int fence, int est, |
|
1211 int expectedModCount) { |
|
1212 super(m, origin, fence, est, expectedModCount); |
|
1213 } |
|
1214 |
|
1215 public EntrySpliterator<K,V> trySplit() { |
|
1216 int hi = getFence(), lo = index, mid = (lo + hi) >>> 1; |
|
1217 return (lo >= mid) ? null : |
|
1218 new EntrySpliterator<K,V>(map, lo, index = mid, est >>>= 1, |
|
1219 expectedModCount); |
|
1220 } |
|
1221 |
|
1222 |
|
1223 public void forEachRemaining(Consumer<? super Map.Entry<K, V>> action) { |
|
1224 int i, hi, mc; |
|
1225 if (action == null) |
|
1226 throw new NullPointerException(); |
|
1227 WeakHashMap<K,V> m = map; |
|
1228 WeakHashMap.Entry<K,V>[] tab = m.table; |
|
1229 if ((hi = fence) < 0) { |
|
1230 mc = expectedModCount = m.modCount; |
|
1231 hi = fence = tab.length; |
|
1232 } |
|
1233 else |
|
1234 mc = expectedModCount; |
|
1235 if (tab.length >= hi && (i = index) >= 0 && i < hi) { |
|
1236 index = hi; |
|
1237 WeakHashMap.Entry<K,V> p = current; |
|
1238 do { |
|
1239 if (p == null) |
|
1240 p = tab[i++]; |
|
1241 else { |
|
1242 Object x = p.get(); |
|
1243 V v = p.value; |
|
1244 p = p.next; |
|
1245 if (x != null) { |
|
1246 @SuppressWarnings("unchecked") K k = |
|
1247 (K) WeakHashMap.unmaskNull(x); |
|
1248 action.accept |
|
1249 (new AbstractMap.SimpleImmutableEntry<K,V>(k, v)); |
|
1250 } |
|
1251 } |
|
1252 } while (p != null || i < hi); |
|
1253 } |
|
1254 if (m.modCount != mc) |
|
1255 throw new ConcurrentModificationException(); |
|
1256 } |
|
1257 |
|
1258 public boolean tryAdvance(Consumer<? super Map.Entry<K,V>> action) { |
|
1259 int hi; |
|
1260 if (action == null) |
|
1261 throw new NullPointerException(); |
|
1262 WeakHashMap.Entry<K,V>[] tab = map.table; |
|
1263 if (tab.length >= (hi = getFence()) && index >= 0) { |
|
1264 while (current != null || index < hi) { |
|
1265 if (current == null) |
|
1266 current = tab[index++]; |
|
1267 else { |
|
1268 Object x = current.get(); |
|
1269 V v = current.value; |
|
1270 current = current.next; |
|
1271 if (x != null) { |
|
1272 @SuppressWarnings("unchecked") K k = |
|
1273 (K) WeakHashMap.unmaskNull(x); |
|
1274 action.accept |
|
1275 (new AbstractMap.SimpleImmutableEntry<K,V>(k, v)); |
|
1276 if (map.modCount != expectedModCount) |
|
1277 throw new ConcurrentModificationException(); |
|
1278 return true; |
|
1279 } |
|
1280 } |
|
1281 } |
|
1282 } |
|
1283 return false; |
|
1284 } |
|
1285 |
|
1286 public int characteristics() { |
|
1287 return Spliterator.DISTINCT; |
|
1288 } |
|
1289 } |
|
1290 |
998 } |
1291 } |