< prev index next >

src/java.base/share/classes/java/util/IdentityHashMap.java

Print this page
rev 54827 : 6394757: AbstractSet.removeAll semantics are surprisingly dependent on relative sizes
Reviewed-by: XXX
   1 /*
   2  * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   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
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


 970             keySet = ks;
 971         }
 972         return ks;
 973     }
 974 
 975     private class KeySet extends AbstractSet<K> {
 976         public Iterator<K> iterator() {
 977             return new KeyIterator();
 978         }
 979         public int size() {
 980             return size;
 981         }
 982         public boolean contains(Object o) {
 983             return containsKey(o);
 984         }
 985         public boolean remove(Object o) {
 986             int oldSize = size;
 987             IdentityHashMap.this.remove(o);
 988             return size != oldSize;
 989         }
 990         /*
 991          * Must revert from AbstractSet's impl to AbstractCollection's, as
 992          * the former contains an optimization that results in incorrect
 993          * behavior when c is a smaller "normal" (non-identity-based) Set.
 994          */
 995         public boolean removeAll(Collection<?> c) {
 996             Objects.requireNonNull(c);
 997             boolean modified = false;
 998             for (Iterator<K> i = iterator(); i.hasNext(); ) {
 999                 if (c.contains(i.next())) {
1000                     i.remove();
1001                     modified = true;
1002                 }
1003             }
1004             return modified;
1005         }
1006         public void clear() {
1007             IdentityHashMap.this.clear();
1008         }
1009         public int hashCode() {
1010             int result = 0;
1011             for (K key : this)
1012                 result += System.identityHashCode(key);
1013             return result;
1014         }
1015         public Object[] toArray() {
1016             return toArray(new Object[0]);
1017         }
1018         @SuppressWarnings("unchecked")
1019         public <T> T[] toArray(T[] a) {
1020             int expectedModCount = modCount;
1021             int size = size();
1022             if (a.length < size)
1023                 a = (T[]) Array.newInstance(a.getClass().getComponentType(), size);
1024             Object[] tab = table;
1025             int ti = 0;


1187             return new EntryIterator();
1188         }
1189         public boolean contains(Object o) {
1190             if (!(o instanceof Map.Entry))
1191                 return false;
1192             Map.Entry<?,?> entry = (Map.Entry<?,?>)o;
1193             return containsMapping(entry.getKey(), entry.getValue());
1194         }
1195         public boolean remove(Object o) {
1196             if (!(o instanceof Map.Entry))
1197                 return false;
1198             Map.Entry<?,?> entry = (Map.Entry<?,?>)o;
1199             return removeMapping(entry.getKey(), entry.getValue());
1200         }
1201         public int size() {
1202             return size;
1203         }
1204         public void clear() {
1205             IdentityHashMap.this.clear();
1206         }
1207         /*
1208          * Must revert from AbstractSet's impl to AbstractCollection's, as
1209          * the former contains an optimization that results in incorrect
1210          * behavior when c is a smaller "normal" (non-identity-based) Set.
1211          */
1212         public boolean removeAll(Collection<?> c) {
1213             Objects.requireNonNull(c);
1214             boolean modified = false;
1215             for (Iterator<Map.Entry<K,V>> i = iterator(); i.hasNext(); ) {
1216                 if (c.contains(i.next())) {
1217                     i.remove();
1218                     modified = true;
1219                 }
1220             }
1221             return modified;
1222         }
1223 
1224         public Object[] toArray() {
1225             return toArray(new Object[0]);
1226         }
1227 
1228         @SuppressWarnings("unchecked")
1229         public <T> T[] toArray(T[] a) {
1230             int expectedModCount = modCount;
1231             int size = size();
1232             if (a.length < size)
1233                 a = (T[]) Array.newInstance(a.getClass().getComponentType(), size);
1234             Object[] tab = table;
1235             int ti = 0;
1236             for (int si = 0; si < tab.length; si += 2) {
1237                 Object key;
1238                 if ((key = tab[si]) != null) { // key present ?
1239                     // more elements than expected -> concurrent modification from other thread
1240                     if (ti >= size) {
1241                         throw new ConcurrentModificationException();
1242                     }
1243                     a[ti++] = (T) new AbstractMap.SimpleEntry<>(unmaskNull(key), tab[si + 1]);


   1 /*
   2  * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   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
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


 970             keySet = ks;
 971         }
 972         return ks;
 973     }
 974 
 975     private class KeySet extends AbstractSet<K> {
 976         public Iterator<K> iterator() {
 977             return new KeyIterator();
 978         }
 979         public int size() {
 980             return size;
 981         }
 982         public boolean contains(Object o) {
 983             return containsKey(o);
 984         }
 985         public boolean remove(Object o) {
 986             int oldSize = size;
 987             IdentityHashMap.this.remove(o);
 988             return size != oldSize;
 989         }
















 990         public void clear() {
 991             IdentityHashMap.this.clear();
 992         }
 993         public int hashCode() {
 994             int result = 0;
 995             for (K key : this)
 996                 result += System.identityHashCode(key);
 997             return result;
 998         }
 999         public Object[] toArray() {
1000             return toArray(new Object[0]);
1001         }
1002         @SuppressWarnings("unchecked")
1003         public <T> T[] toArray(T[] a) {
1004             int expectedModCount = modCount;
1005             int size = size();
1006             if (a.length < size)
1007                 a = (T[]) Array.newInstance(a.getClass().getComponentType(), size);
1008             Object[] tab = table;
1009             int ti = 0;


1171             return new EntryIterator();
1172         }
1173         public boolean contains(Object o) {
1174             if (!(o instanceof Map.Entry))
1175                 return false;
1176             Map.Entry<?,?> entry = (Map.Entry<?,?>)o;
1177             return containsMapping(entry.getKey(), entry.getValue());
1178         }
1179         public boolean remove(Object o) {
1180             if (!(o instanceof Map.Entry))
1181                 return false;
1182             Map.Entry<?,?> entry = (Map.Entry<?,?>)o;
1183             return removeMapping(entry.getKey(), entry.getValue());
1184         }
1185         public int size() {
1186             return size;
1187         }
1188         public void clear() {
1189             IdentityHashMap.this.clear();
1190         }

















1191         public Object[] toArray() {
1192             return toArray(new Object[0]);
1193         }
1194 
1195         @SuppressWarnings("unchecked")
1196         public <T> T[] toArray(T[] a) {
1197             int expectedModCount = modCount;
1198             int size = size();
1199             if (a.length < size)
1200                 a = (T[]) Array.newInstance(a.getClass().getComponentType(), size);
1201             Object[] tab = table;
1202             int ti = 0;
1203             for (int si = 0; si < tab.length; si += 2) {
1204                 Object key;
1205                 if ((key = tab[si]) != null) { // key present ?
1206                     // more elements than expected -> concurrent modification from other thread
1207                     if (ti >= size) {
1208                         throw new ConcurrentModificationException();
1209                     }
1210                     a[ti++] = (T) new AbstractMap.SimpleEntry<>(unmaskNull(key), tab[si + 1]);


< prev index next >