jdk/src/share/classes/java/util/WeakHashMap.java
changeset 17168 b7d3500f2516
parent 14342 8435a30053c1
child 17939 bd750ec19d82
equal deleted inserted replaced
17167:87067e3340d3 17168:b7d3500f2516
     1 /*
     1 /*
     2  * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    22  * or visit www.oracle.com if you need additional information or have any
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 
    25 
    26 package java.util;
    26 package java.util;
       
    27 
    27 import java.lang.ref.WeakReference;
    28 import java.lang.ref.WeakReference;
    28 import java.lang.ref.ReferenceQueue;
    29 import java.lang.ref.ReferenceQueue;
       
    30 import java.util.function.Consumer;
    29 
    31 
    30 
    32 
    31 /**
    33 /**
    32  * Hash table based implementation of the <tt>Map</tt> interface, with
    34  * Hash table based implementation of the <tt>Map</tt> interface, with
    33  * <em>weak keys</em>.
    35  * <em>weak keys</em>.
   896         }
   898         }
   897 
   899 
   898         public void clear() {
   900         public void clear() {
   899             WeakHashMap.this.clear();
   901             WeakHashMap.this.clear();
   900         }
   902         }
       
   903 
       
   904         public Spliterator<K> spliterator() {
       
   905             return new KeySpliterator<>(WeakHashMap.this, 0, -1, 0, 0);
       
   906         }
   901     }
   907     }
   902 
   908 
   903     /**
   909     /**
   904      * Returns a {@link Collection} view of the values contained in this map.
   910      * Returns a {@link Collection} view of the values contained in this map.
   905      * The collection is backed by the map, so changes to the map are
   911      * The collection is backed by the map, so changes to the map are
   931             return containsValue(o);
   937             return containsValue(o);
   932         }
   938         }
   933 
   939 
   934         public void clear() {
   940         public void clear() {
   935             WeakHashMap.this.clear();
   941             WeakHashMap.this.clear();
       
   942         }
       
   943 
       
   944         public Spliterator<V> spliterator() {
       
   945             return new ValueSpliterator<>(WeakHashMap.this, 0, -1, 0, 0);
   936         }
   946         }
   937     }
   947     }
   938 
   948 
   939     /**
   949     /**
   940      * Returns a {@link Set} view of the mappings contained in this map.
   950      * Returns a {@link Set} view of the mappings contained in this map.
   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 }