--- jsr166/src/main/java/util/HashMap.java 2017/08/23 05:33:00 1.1 +++ jsr166/src/main/java/util/HashMap.java 2018/08/10 19:35:20 1.7 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,7 @@ import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Function; +import jdk.internal.misc.SharedSecrets; /** * Hash table based implementation of the {@code Map} interface. This @@ -375,12 +376,7 @@ public class HashMap extends Abstra * Returns a power of two size for the given target capacity. */ static final int tableSizeFor(int cap) { - int n = cap - 1; - n |= n >>> 1; - n |= n >>> 2; - n |= n >>> 4; - n |= n >>> 8; - n |= n >>> 16; + int n = -1 >>> Integer.numberOfLeadingZeros(cap - 1); return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1; } @@ -1267,9 +1263,7 @@ public class HashMap extends Abstra @Override public V merge(K key, V value, BiFunction remappingFunction) { - if (value == null) - throw new NullPointerException(); - if (remappingFunction == null) + if (value == null || remappingFunction == null) throw new NullPointerException(); int hash = hash(key); Node[] tab; Node first; int n, i; @@ -1312,8 +1306,7 @@ public class HashMap extends Abstra else removeNode(hash, key, null, false, true); return v; - } - if (value != null) { + } else { if (t != null) t.putTreeVal(this, tab, hash, key, value); else { @@ -1324,8 +1317,8 @@ public class HashMap extends Abstra ++modCount; ++size; afterNodeInsertion(true); + return value; } - return value; } @Override @@ -1394,9 +1387,10 @@ public class HashMap extends Abstra } /** - * Save the state of the {@code HashMap} instance to a stream (i.e., - * serialize it). + * Saves this map to a stream (that is, serializes it). * + * @param s the stream + * @throws IOException if an I/O error occurs * @serialData The capacity of the HashMap (the length of the * bucket array) is emitted (int), followed by the * size (an int, the number of key-value @@ -1415,8 +1409,11 @@ public class HashMap extends Abstra } /** - * Reconstitute the {@code HashMap} instance from a stream (i.e., - * deserialize it). + * Reconstitutes this map from a stream (that is, deserializes it). + * @param s the stream + * @throws ClassNotFoundException if the class of a serialized object + * could not be found + * @throws IOException if an I/O error occurs */ private void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException { @@ -1444,6 +1441,10 @@ public class HashMap extends Abstra float ft = (float)cap * lf; threshold = ((cap < MAXIMUM_CAPACITY && ft < MAXIMUM_CAPACITY) ? (int)ft : Integer.MAX_VALUE); + + // Check Map.Entry[].class since it's the nearest public type to + // what we're actually creating. + SharedSecrets.getJavaObjectInputStreamAccess().checkArray(s, Map.Entry[].class, cap); @SuppressWarnings({"rawtypes","unchecked"}) Node[] tab = (Node[])new Node[cap]; table = tab; @@ -2144,7 +2145,7 @@ public class HashMap extends Abstra if (replacement != p) { TreeNode pp = replacement.parent = p.parent; if (pp == null) - root = replacement; + (root = replacement).red = false; else if (p == pp.left) pp.left = replacement; else