--- old/src/java.base/share/classes/java/util/TreeMap.java 2020-05-03 07:52:12.412000000 +0000 +++ new/src/java.base/share/classes/java/util/TreeMap.java 2020-05-03 07:52:12.032000000 +0000 @@ -1790,6 +1790,38 @@ return m.put(key, value); } + public V putIfAbsent(K key, V value) { + if (!inRange(key)) + throw new IllegalArgumentException("key out of range"); + return m.putIfAbsent(key, value); + } + + public V merge(K key, V value, BiFunction remappingFunction) { + if (!inRange(key)) + throw new IllegalArgumentException("key out of range"); + return m.merge(key, value, remappingFunction); + } + + public V computeIfAbsent(K key, Function mappingFunction) { + if (!inRange(key)) { + if (mappingFunction.apply(key) == null) return null; + throw new IllegalArgumentException("key out of range"); + } + return m.computeIfAbsent(key, mappingFunction); + } + + public V compute(K key, BiFunction remappingFunction) { + if (!inRange(key)) { + if (remappingFunction.apply(key, null) == null) return null; + throw new IllegalArgumentException("key out of range"); + } + return m.compute(key, remappingFunction); + } + + public V computeIfPresent(K key, BiFunction remappingFunction) { + return !inRange(key) ? null : m.computeIfPresent(key, remappingFunction); + } + public final V get(Object key) { return !inRange(key) ? null : m.get(key); } --- old/test/jdk/java/util/Map/InPlaceOpsCollisions.java 2020-05-03 07:52:13.304000000 +0000 +++ new/test/jdk/java/util/Map/InPlaceOpsCollisions.java 2020-05-03 07:52:12.932000000 +0000 @@ -523,7 +523,8 @@ new Object[]{"HashMap", (Supplier>) HashMap::new}, new Object[]{"LinkedHashMap", (Supplier>) LinkedHashMap::new}, new Object[]{"TreeMap", (Supplier>) TreeMap::new}, - new Object[]{"TreeMap(cmp)", (Supplier>) () -> new TreeMap<>(Comparator.reverseOrder())} + new Object[]{"TreeMap(cmp)", (Supplier>) () -> new TreeMap<>(Comparator.reverseOrder())}, + new Object[]{"TreeMap.descendingMap", (Supplier>) () -> new TreeMap<>().descendingMap()} ).iterator(); } } --- old/test/jdk/java/util/Map/MapWithCollisionsProviders.java 2020-05-03 07:52:14.096000000 +0000 +++ new/test/jdk/java/util/Map/MapWithCollisionsProviders.java 2020-05-03 07:52:13.760000000 +0000 @@ -193,6 +193,8 @@ new IdentityHashMap<>(), keys, val)); cases.add(createCase("TreeMap with " + desc, new TreeMap<>(), keys, val)); + cases.add(createCase("Descending TreeMap with " + desc, + new TreeMap<>().descendingMap(), keys, val)); cases.add(createCase("WeakHashMap with " + desc, new WeakHashMap<>(), keys, val)); cases.add(createCase("ConcurrentHashMap with " + desc, --- old/test/jdk/java/util/NavigableMap/LockStep.java 2020-05-03 07:52:14.960000000 +0000 +++ new/test/jdk/java/util/NavigableMap/LockStep.java 2020-05-03 07:52:14.564000000 +0000 @@ -46,11 +46,11 @@ import java.util.Comparator; import java.util.HashSet; import java.util.Iterator; -import java.util.List; import java.util.Map; import java.util.NavigableMap; import java.util.NavigableSet; import java.util.NoSuchElementException; +import java.util.Objects; import java.util.Random; import java.util.Set; import java.util.TreeMap; @@ -79,26 +79,26 @@ static void realMain(String[] args) { size = intArg(args, 0, DEFAULT_SIZE); - lockSteps(new TreeMap(), - new ConcurrentSkipListMap()); - lockSteps(new TreeMap(), - Collections.checkedNavigableMap(new TreeMap(), Integer.class, Integer.class)); - lockSteps(new TreeMap(), - Collections.synchronizedNavigableMap(new TreeMap())); - lockSteps(new TreeMap(reverseOrder()), - new ConcurrentSkipListMap(reverseOrder())); - - lockSteps(new TreeSet(), - new ConcurrentSkipListSet()); - lockSteps(new TreeSet(), - Collections.checkedNavigableSet(new TreeSet(), Integer.class)); - lockSteps(new TreeSet(), - Collections.synchronizedNavigableSet(new TreeSet())); - lockSteps(new TreeSet(reverseOrder()), - new ConcurrentSkipListSet(reverseOrder())); + lockSteps(new TreeMap<>(), + new ConcurrentSkipListMap<>()); + lockSteps(new TreeMap<>(), + Collections.checkedNavigableMap(new TreeMap<>(), Integer.class, Integer.class)); + lockSteps(new TreeMap<>(), + Collections.synchronizedNavigableMap(new TreeMap<>())); + lockSteps(new TreeMap<>(reverseOrder()), + new ConcurrentSkipListMap<>(reverseOrder())); + + lockSteps(new TreeSet<>(), + new ConcurrentSkipListSet<>()); + lockSteps(new TreeSet<>(), + Collections.checkedNavigableSet(new TreeSet<>(), Integer.class)); + lockSteps(new TreeSet<>(), + Collections.synchronizedNavigableSet(new TreeSet<>())); + lockSteps(new TreeSet<>(reverseOrder()), + new ConcurrentSkipListSet<>(reverseOrder())); } - static void lockSteps(NavigableMap m1, NavigableMap m2) { + static void lockSteps(NavigableMap m1, NavigableMap m2) { if (maybe(4)) m1 = serialClone(m1); if (maybe(4)) m2 = serialClone(m2); lockStep(m1, @@ -119,7 +119,7 @@ fullTailMap(m2.descendingMap())); } - static void lockSteps(NavigableSet s1, NavigableSet s2) { + static void lockSteps(NavigableSet s1, NavigableSet s2) { if (maybe(4)) s1 = serialClone(s1); if (maybe(4)) s2 = serialClone(s2); lockStep(s1, @@ -140,47 +140,47 @@ fullTailSet(s2.descendingSet())); } - static boolean isAscending(NavigableMap m) { - Comparator cmp = m.comparator(); + static boolean isAscending(NavigableMap m) { + var cmp = m.comparator(); return (cmp == null || cmp.compare(1, 2) < 0); } - static NavigableMap fullSubMap(NavigableMap m) { + static NavigableMap fullSubMap(NavigableMap m) { return isAscending(m) ? m.subMap(Integer.MIN_VALUE, true, Integer.MAX_VALUE, true) : m.subMap(Integer.MAX_VALUE, true, Integer.MIN_VALUE, true); } - static NavigableMap fullHeadMap(NavigableMap m) { + static NavigableMap fullHeadMap(NavigableMap m) { return isAscending(m) ? m.headMap(Integer.MAX_VALUE, true) : m.headMap(Integer.MIN_VALUE, true); } - static NavigableMap fullTailMap(NavigableMap m) { + static NavigableMap fullTailMap(NavigableMap m) { return isAscending(m) ? m.tailMap(Integer.MIN_VALUE, true) : m.tailMap(Integer.MAX_VALUE, true); } - static boolean isAscending(NavigableSet s) { - Comparator cmp = s.comparator(); + static boolean isAscending(NavigableSet s) { + var cmp = s.comparator(); return (cmp == null || cmp.compare(1, 2) < 0); } - static NavigableSet fullSubSet(NavigableSet s) { + static NavigableSet fullSubSet(NavigableSet s) { return isAscending(s) ? s.subSet(Integer.MIN_VALUE, true, Integer.MAX_VALUE, true) : s.subSet(Integer.MAX_VALUE, true, Integer.MIN_VALUE, true); } - static NavigableSet fullHeadSet(NavigableSet s) { + static NavigableSet fullHeadSet(NavigableSet s) { return isAscending(s) ? s.headSet(Integer.MAX_VALUE, true) : s.headSet(Integer.MIN_VALUE, true); } - static NavigableSet fullTailSet(NavigableSet s) { + static NavigableSet fullTailSet(NavigableSet s) { return isAscending(s) ? s.tailSet(Integer.MIN_VALUE, true) : s.tailSet(Integer.MAX_VALUE, true); @@ -231,21 +231,17 @@ equal(it.next(), expected); } - static Comparator comparator(NavigableSet s) { - Comparator cmp = s.comparator(); - return cmp != null ? cmp : new Comparator() { - public int compare(Object o1, Object o2) { - return ((Comparable) o1).compareTo(o2); }}; + static Comparator comparator(NavigableSet s) { + var cmp = s.comparator(); + return cmp != null ? cmp : Comparator.naturalOrder(); } - static Comparator comparator(NavigableMap m) { - Comparator cmp = m.comparator(); - return cmp != null ? cmp : new Comparator() { - public int compare(Object o1, Object o2) { - return ((Comparable) o1).compareTo(o2); }}; + static Comparator comparator(NavigableMap m) { + var cmp = m.comparator(); + return cmp != null ? cmp : Comparator.naturalOrder(); } - static void checkNavigableSet(final NavigableSet s) { + static void checkNavigableSet(final NavigableSet s) { if (s.comparator() == null) check(s.descendingSet().descendingSet().comparator() == null); equal(s.isEmpty(), s.size() == 0); @@ -259,7 +255,7 @@ } } } - Comparator cmp = comparator(s); + var cmp = comparator(s); if (s.isEmpty()) { THROWS(NoSuchElementException.class, () -> s.first(), @@ -269,8 +265,8 @@ equal(null, s.ceiling(1)); equal(null, s.higher(1)); } else { - Object a = s.first(); - Object z = s.last(); + Integer a = s.first(); + Integer z = s.last(); equal(s.lower(a), null); equal(s.higher(z), null); equal2(s, s.tailSet(a)); @@ -285,28 +281,27 @@ equal2(s.headSet(a, true), singleton(a)); equal2(s.tailSet(z, true), singleton(z)); } - Iterator[] its = new Iterator[] { + Iterator[] its = new Iterator[] { s.iterator(), s.descendingSet().descendingSet().iterator(), }; - for (final Iterator it : its) + for (final Iterator it : its) if (maybe(4)) THROWS(IllegalStateException.class, () -> it.remove()); - Object prev = null; - for (Object e : s) { + Integer prev = null; + for (final Integer e : s) { check(s.contains(e)); - for (Iterator it : its) equalNext(it, e); + for (Iterator it : its) equalNext(it, e); equal(e, s.ceiling(e)); equal(e, s.floor(e)); check(s.higher(e) == null || cmp.compare(e, s.higher(e)) < 0); equal(s.lower(e), prev); - if (prev == null) { - } else { + if (prev != null) { check(cmp.compare(prev, e) < 0); } prev = e; } - for (final Iterator it : its) { + for (final Iterator it : its) { if (maybe(2)) check(! it.hasNext()); Fun fun = () -> it.next(); @@ -324,7 +319,7 @@ check(! it2.hasNext()); } - static void equalSetsLeaf(final Set s1, final Set s2) { + static void equalSetsLeaf(final Set s1, final Set s2) { equal2(s1, s2); equal( s1.size(), s2.size()); equal( s1.isEmpty(), s2.isEmpty()); @@ -333,8 +328,8 @@ equal( s1.containsAll(s2), s2.containsAll(s1)); } - static void equalNavigableSetsLeaf(final NavigableSet s1, - final NavigableSet s2) { + static void equalNavigableSetsLeaf(final NavigableSet s1, + final NavigableSet s2) { equal2(s1, s2); equal( s1.size(), s2.size()); equal( s1.isEmpty(), s2.isEmpty()); @@ -350,16 +345,16 @@ checkNavigableSet(s2); } - static void equalNavigableSets(final NavigableSet s1, - final NavigableSet s2) { + static void equalNavigableSets(final NavigableSet s1, + final NavigableSet s2) { equalNavigableSetsLeaf(s1, s2); equalNavigableSetsLeaf(s1.descendingSet(), s2.descendingSet()); equalNavigableSetsLeaf(s1.descendingSet().descendingSet(), s2); - Object min = s1.isEmpty() ? Integer.MIN_VALUE : s1.first(); - Object max = s2.isEmpty() ? Integer.MAX_VALUE : s2.last(); + Integer min = s1.isEmpty() ? Integer.MIN_VALUE : s1.first(); + Integer max = s2.isEmpty() ? Integer.MAX_VALUE : s2.last(); if (s1.comparator() != null && s1.comparator().compare(min, max) > 0) { - Object tmp = min; min = max; max = tmp; + Integer tmp = min; min = max; max = tmp; } equalNavigableSetsLeaf(s1.subSet(min, true, max, true), @@ -368,31 +363,29 @@ s2.tailSet(min, true)); equalNavigableSetsLeaf(s1.headSet(max, true), s2.headSet(max, true)); - equalNavigableSetsLeaf((NavigableSet) s1.subSet(min, max), - (NavigableSet) s2.subSet(min, max)); - equalNavigableSetsLeaf((NavigableSet) s1.tailSet(min), - (NavigableSet) s2.tailSet(min)); - equalNavigableSetsLeaf((NavigableSet) s1.headSet(max), - (NavigableSet) s2.headSet(max)); + equalNavigableSetsLeaf((NavigableSet) s1.subSet(min, max), + (NavigableSet) s2.subSet(min, max)); + equalNavigableSetsLeaf((NavigableSet) s1.tailSet(min), + (NavigableSet) s2.tailSet(min)); + equalNavigableSetsLeaf((NavigableSet) s1.headSet(max), + (NavigableSet) s2.headSet(max)); } // Destined for a Collections.java near you? static T[] concat(T[]... arrays) { int len = 0; - for (int i = 0; i < arrays.length; i++) - len += arrays[i].length; + for (T[] arr : arrays) len += arr.length; T[] a = (T[])java.lang.reflect.Array .newInstance(arrays[0].getClass().getComponentType(), len); int k = 0; - for (int i = 0; i < arrays.length; i++) { - T[] array = arrays[i]; - System.arraycopy(array, 0, a, k, array.length); - k += array.length; + for (T[] arr : arrays) { + System.arraycopy(arr, 0, a, k, arr.length); + k += arr.length; } return a; } - static void checkNavigableMap(final NavigableMap m) { + static void checkNavigableMap(final NavigableMap m) { if (m.comparator() == null) { check(m.descendingMap().descendingMap().comparator() == null); check(m.descendingKeySet().descendingSet().comparator() == null); @@ -402,7 +395,7 @@ if (maybe(4)) equal2(m, serialClone(m)); equal2(m.keySet(), m.descendingKeySet()); - Comparator cmp = comparator(m); + var cmp = comparator(m); if (m.isEmpty()) { THROWS(NoSuchElementException.class, () -> m.firstKey(), @@ -420,8 +413,8 @@ equal(null, m.ceilingEntry(1)); equal(null, m.higherEntry(1)); } else { - Object a = m.firstKey(); - Object z = m.lastKey(); + Integer a = m.firstKey(); + Integer z = m.lastKey(); equal(m.lowerKey(a), null); equal(m.higherKey(z), null); equal(a, m.firstEntry().getKey()); @@ -439,32 +432,32 @@ equal2(m.tailMap(z, true), singletonMap(z, m.get(z))); } - Iterator[] kits = new Iterator[] { + Iterator[] kits = new Iterator[] { m.keySet().iterator(), m.descendingMap().descendingKeySet().iterator(), m.descendingKeySet().descendingSet().iterator(), }; - Iterator[] vits = new Iterator[] { + Iterator[] vits = new Iterator[] { m.values().iterator(), m.descendingMap().descendingMap().values().iterator(), }; - Iterator[] eits = new Iterator[] { + Iterator[] eits = new Iterator[] { m.entrySet().iterator(), m.descendingMap().descendingMap().entrySet().iterator(), }; - Iterator[] its = concat(kits, vits, eits); - for (final Iterator it : its) + Iterator[] its = concat(kits, vits, eits); + for (final Iterator it : its) if (maybe(4)) THROWS(IllegalStateException.class, () -> it.remove()); - Map.Entry prev = null; - for (Map.Entry e : (Set) m.entrySet()) { - Object k = e.getKey(); - Object v = e.getValue(); + Map.Entry prev = null; + for (var e : m.entrySet()) { + Integer k = e.getKey(); + Integer v = e.getValue(); check(m.containsKey(k)); check(m.containsValue(v)); - for (Iterator kit : kits) equalNext(kit, k); - for (Iterator vit : vits) equalNext(vit, v); - for (Iterator eit : eits) equalNext(eit, e); + for (var kit : kits) equalNext(kit, k); + for (var vit : vits) equalNext(vit, v); + for (var eit : eits) equalNext(eit, e); equal(k, m.ceilingKey(k)); equal(k, m.ceilingEntry(k).getKey()); equal(k, m.floorKey(k)); @@ -480,7 +473,7 @@ } prev = e; } - for (final Iterator it : its) { + for (final var it : its) { if (maybe(2)) check(! it.hasNext()); Fun fun = () -> it.next(); @@ -488,8 +481,8 @@ } } - static void equalNavigableMapsLeaf(final NavigableMap m1, - final NavigableMap m2) { + static void equalNavigableMapsLeaf(final NavigableMap m1, + final NavigableMap m2) { equal2(m1, m2); equal( m1.size(), m2.size()); equal( m1.isEmpty(), m2.isEmpty()); @@ -501,8 +494,8 @@ checkNavigableMap(m2); } - static void equalNavigableMaps(NavigableMap m1, - NavigableMap m2) { + static void equalNavigableMaps(NavigableMap m1, + NavigableMap m2) { equalNavigableMapsLeaf(m1, m2); equalSetsLeaf(m1.keySet(), m2.keySet()); equalNavigableSets(m1.navigableKeySet(), @@ -515,8 +508,8 @@ m2.descendingMap()); equalNavigableMapsLeaf(m1.descendingMap().descendingMap(), m2); - equalNavigableSetsLeaf((NavigableSet) m1.descendingMap().keySet(), - (NavigableSet) m2.descendingMap().keySet()); + equalNavigableSetsLeaf((NavigableSet) m1.descendingMap().keySet(), + (NavigableSet) m2.descendingMap().keySet()); equalNavigableSetsLeaf(m1.descendingMap().descendingKeySet(), m2.descendingMap().descendingKeySet()); equal2(m1.descendingMap().entrySet(), @@ -525,11 +518,11 @@ //---------------------------------------------------------------- // submaps //---------------------------------------------------------------- - Object min = Integer.MIN_VALUE; - Object max = Integer.MAX_VALUE; + Integer min = Integer.MIN_VALUE; + Integer max = Integer.MAX_VALUE; if (m1.comparator() != null && m1.comparator().compare(min, max) > 0) { - Object tmp = min; min = max; max = tmp; + Integer tmp = min; min = max; max = tmp; } switch (rnd.nextInt(6)) { case 0: @@ -545,107 +538,119 @@ m2.headMap(max, true)); break; case 3: - equalNavigableMapsLeaf((NavigableMap) m1.subMap(min, max), - (NavigableMap) m2.subMap(min, max)); + equalNavigableMapsLeaf((NavigableMap) m1.subMap(min, max), + (NavigableMap) m2.subMap(min, max)); break; case 4: - equalNavigableMapsLeaf((NavigableMap) m1.tailMap(min), - (NavigableMap) m2.tailMap(min)); + equalNavigableMapsLeaf((NavigableMap) m1.tailMap(min), + (NavigableMap) m2.tailMap(min)); break; case 5: - equalNavigableMapsLeaf((NavigableMap) m1.headMap(max), - (NavigableMap) m2.headMap(max)); + equalNavigableMapsLeaf((NavigableMap) m1.headMap(max), + (NavigableMap) m2.headMap(max)); break; } } - abstract static class MapFrobber { abstract void frob(NavigableMap m); } - abstract static class SetFrobber { abstract void frob(NavigableSet m); } + interface MapFrobber { void frob(NavigableMap m); } + interface SetFrobber { void frob(NavigableSet m); } - static MapFrobber randomAdder(NavigableMap m) { + static MapFrobber randomAdder(NavigableMap m) { final Integer k = unusedKey(m); final MapFrobber[] randomAdders = { - new MapFrobber() {void frob(NavigableMap m) { - equal(m.put(k, k+1), null); - equal(m.get(k), k+1); + map -> { + equal(map.put(k, k + 1), null); + equal(map.get(k), k + 1); if (maybe(4)) { - equal(m.put(k, k+1), k+1); - equal(m.get(k), k+1);}}}, - new MapFrobber() {void frob(NavigableMap m) { - m.descendingMap().put(k, k+1); - equal(m.get(k), k+1);}}, - new MapFrobber() {void frob(NavigableMap m) { - m.tailMap(k,true).headMap(k,true).put(k,k+1);}}, - new MapFrobber() {void frob(NavigableMap m) { - m.tailMap(k,true).headMap(k,true).descendingMap().put(k,k+1);}} + equal(map.put(k, k + 1), k + 1); + equal(map.get(k), k + 1);}}, + map -> { + map.descendingMap().put(k, k + 1); + equal(map.get(k), k + 1);}, + map -> map.tailMap(k,true).headMap(k,true).put(k, k + 1), + map -> { + equal(map.tailMap(k,true).headMap(k,true).putIfAbsent(k, k + 1), null); + equal(map.tailMap(k,true).headMap(k,true).putIfAbsent(k, k + 1), k + 1);}, + map -> { + equal(map.tailMap(k,true).headMap(k,true).merge(k,k,Integer::sum), k); + equal(map.tailMap(k,true).headMap(k,true).merge(k,1,Integer::sum), k+1);}, + map -> equal(map.subMap(k,true, k, true).computeIfAbsent(k, key -> key + 1), k + 1), + map -> { + equal(map.subMap(k,true, k, true).computeIfPresent(k, (key, val) -> 1), null); + equal(map.tailMap(k,true).compute(k, (key, val) -> { + equal(val, null); + return 1; + }), 1); + equal(map.headMap(k, true).computeIfPresent(k, (key, val) -> val + key), k + 1); + equal(map.tailMap(k, false).computeIfPresent(k, (key, val) -> 1), null); + equal(map.headMap(k, false).compute(k, (key, val) -> null), null); + equal(map.tailMap(k, false).computeIfAbsent(k, key -> null), null); + }, + map -> map.tailMap(k,true).headMap(k,true).descendingMap().put(k, k + 1) }; - return new MapFrobber() {void frob(NavigableMap m) { - randomAdders[rnd.nextInt(randomAdders.length)].frob(m); - if (maybe(2)) equal(m.get(k), k+1); + return map -> { + randomAdders[rnd.nextInt(randomAdders.length)].frob(map); + if (maybe(2)) equal(map.get(k), k + 1); if (maybe(4)) { - equal(m.put(k, k+1), k+1); - equal(m.get(k), k+1);}}}; + equal(map.put(k, k + 1), k + 1); + equal(map.get(k), k + 1);}}; } - static SetFrobber randomAdder(NavigableSet s) { + static SetFrobber randomAdder(NavigableSet s) { final Integer e = unusedElt(s); final SetFrobber[] randomAdders = { - new SetFrobber() {void frob(NavigableSet s) { - check(s.add(e));}}, - new SetFrobber() {void frob(NavigableSet s) { - s.descendingSet().add(e);}}, - new SetFrobber() {void frob(NavigableSet s) { - s.tailSet(e,true).headSet(e,true).add(e);}}, - new SetFrobber() {void frob(NavigableSet s) { - s.descendingSet().tailSet(e,true).headSet(e,true).add(e);}} + set -> check(set.add(e)), + set -> set.descendingSet().add(e), + set -> set.tailSet(e,true).headSet(e,true).add(e), + set -> set.descendingSet().tailSet(e,true).headSet(e,true).add(e) }; - return new SetFrobber() {void frob(NavigableSet s) { - if (maybe(2)) check(! s.contains(e)); - randomAdders[rnd.nextInt(randomAdders.length)].frob(s); - if (maybe(2)) check(! s.add(e)); - if (maybe(2)) check(s.contains(e));}}; + return set -> { + if (maybe(2)) check(! set.contains(e)); + randomAdders[rnd.nextInt(randomAdders.length)].frob(set); + if (maybe(2)) check(! set.add(e)); + if (maybe(2)) check(set.contains(e));}; } - static Integer unusedElt(NavigableSet s) { + static Integer unusedElt(NavigableSet s) { Integer e; do { e = rnd.nextInt(1024); } while (s.contains(e)); return e; } - static Integer unusedKey(NavigableMap m) { + static Integer unusedKey(NavigableMap m) { Integer k; do { k = rnd.nextInt(1024); } while (m.containsKey(k)); return k; } - static Integer usedKey(NavigableMap m) { + static Integer usedKey(NavigableMap m) { Integer x = rnd.nextInt(1024); - Integer floor = (Integer) m.floorKey(x); - Integer ceiling = (Integer) m.ceilingKey(x); + Integer floor = m.floorKey(x); + Integer ceiling = m.ceilingKey(x); if (floor != null) return floor; check(ceiling != null); return ceiling; } - static Integer usedElt(NavigableSet s) { + static Integer usedElt(NavigableSet s) { Integer x = rnd.nextInt(1024); - Integer floor = (Integer) s.floor(x); - Integer ceiling = (Integer) s.ceiling(x); + Integer floor = s.floor(x); + Integer ceiling = s.ceiling(x); if (floor != null) return floor; check(ceiling != null); return ceiling; } - static void checkUnusedKey(NavigableMap m, Object k) { + static void checkUnusedKey(NavigableMap m, Integer k) { check(! m.containsKey(k)); equal(m.get(k), null); if (maybe(2)) equal(m.remove(k), null); } - static void checkUnusedElt(NavigableSet s, Object e) { + static void checkUnusedElt(NavigableSet s, Integer e) { if (maybe(2)) check(! s.contains(e)); if (maybe(2)) { @@ -656,32 +661,32 @@ check(! s.remove(e)); } - static Fun remover(final Iterator it) { + static Fun remover(final Iterator it) { return () -> it.remove(); } - static MapFrobber randomRemover(NavigableMap m) { + static MapFrobber randomRemover(NavigableMap m) { final Integer k = usedKey(m); final MapFrobber[] randomRemovers = { - new MapFrobber() {void frob(NavigableMap m) { - Map.Entry e = m.firstEntry(); - equal(m.pollFirstEntry(), e); - checkUnusedKey(m, e.getKey());}}, - new MapFrobber() {void frob(NavigableMap m) { - Map.Entry e = m.lastEntry(); - equal(m.pollLastEntry(), e); - checkUnusedKey(m, e.getKey());}}, - new MapFrobber() {void frob(NavigableMap m) { - check(m.remove(k) != null); - checkUnusedKey(m, k);}}, - new MapFrobber() {void frob(NavigableMap m) { - m.subMap(k, true, k, true).clear(); - checkUnusedKey(m, k);}}, - new MapFrobber() {void frob(NavigableMap m) { - m.descendingMap().subMap(k, true, k, true).clear(); - checkUnusedKey(m, k);}}, - new MapFrobber() {void frob(NavigableMap m) { - final Iterator it = m.keySet().iterator(); + map -> { + var e = map.firstEntry(); + equal(map.pollFirstEntry(), e); + checkUnusedKey(map, e.getKey());}, + map -> { + var e = map.lastEntry(); + equal(map.pollLastEntry(), e); + checkUnusedKey(map, e.getKey());}, + map -> { + check(map.remove(k) != null); + checkUnusedKey(map, k);}, + map -> { + map.subMap(k, true, k, true).clear(); + checkUnusedKey(map, k);}, + map -> { + map.descendingMap().subMap(k, true, k, true).clear(); + checkUnusedKey(map, k);}, + map -> { + final var it = map.keySet().iterator(); while (it.hasNext()) if (it.next().equals(k)) { it.remove(); @@ -689,9 +694,9 @@ THROWS(IllegalStateException.class, () -> it.remove()); } - checkUnusedKey(m, k);}}, - new MapFrobber() {void frob(NavigableMap m) { - final Iterator it = m.navigableKeySet().descendingIterator(); + checkUnusedKey(map, k);}, + map -> { + final var it = map.navigableKeySet().descendingIterator(); while (it.hasNext()) if (it.next().equals(k)) { it.remove(); @@ -699,44 +704,44 @@ THROWS(IllegalStateException.class, () -> it.remove()); } - checkUnusedKey(m, k);}}, - new MapFrobber() {void frob(NavigableMap m) { - final Iterator it = m.entrySet().iterator(); + checkUnusedKey(map, k);}, + map -> { + final var it = map.entrySet().iterator(); while (it.hasNext()) if (it.next().getKey().equals(k)) { it.remove(); if (maybe(2)) THROWS(IllegalStateException.class, remover(it)); } - checkUnusedKey(m, k);}}, + checkUnusedKey(map, k);}, }; return randomRemovers[rnd.nextInt(randomRemovers.length)]; } - static SetFrobber randomRemover(NavigableSet s) { + static SetFrobber randomRemover(NavigableSet s) { final Integer e = usedElt(s); final SetFrobber[] randomRemovers = { - new SetFrobber() {void frob(NavigableSet s) { - Object e = s.first(); - equal(s.pollFirst(), e); - checkUnusedElt(s, e);}}, - new SetFrobber() {void frob(NavigableSet s) { - Object e = s.last(); - equal(s.pollLast(), e); - checkUnusedElt(s, e);}}, - new SetFrobber() {void frob(NavigableSet s) { - check(s.remove(e)); - checkUnusedElt(s, e);}}, - new SetFrobber() {void frob(NavigableSet s) { - s.subSet(e, true, e, true).clear(); - checkUnusedElt(s, e);}}, - new SetFrobber() {void frob(NavigableSet s) { - s.descendingSet().subSet(e, true, e, true).clear(); - checkUnusedElt(s, e);}}, - new SetFrobber() {void frob(NavigableSet s) { - final Iterator it = s.iterator(); + set -> { + var fst = set.first(); + equal(set.pollFirst(), fst); + checkUnusedElt(set, fst);}, + set -> { + var lst = set.last(); + equal(set.pollLast(), lst); + checkUnusedElt(set, lst);}, + set -> { + check(set.remove(e)); + checkUnusedElt(set, e);}, + set -> { + set.subSet(e, true, e, true).clear(); + checkUnusedElt(set, e);}, + set -> { + set.descendingSet().subSet(e, true, e, true).clear(); + checkUnusedElt(set, e);}, + set -> { + final var it = set.iterator(); while (it.hasNext()) if (it.next().equals(e)) { it.remove(); @@ -744,9 +749,9 @@ THROWS(IllegalStateException.class, () -> it.remove()); } - checkUnusedElt(s, e);}}, - new SetFrobber() {void frob(NavigableSet s) { - final Iterator it = s.descendingSet().iterator(); + checkUnusedElt(set, e);}, + set -> { + final var it = set.descendingSet().iterator(); while (it.hasNext()) if (it.next().equals(e)) { it.remove(); @@ -754,9 +759,9 @@ THROWS(IllegalStateException.class, () -> it.remove()); } - checkUnusedElt(s, e);}}, - new SetFrobber() {void frob(NavigableSet s) { - final Iterator it = s.descendingIterator(); + checkUnusedElt(set, e);}, + set -> { + final var it = set.descendingIterator(); while (it.hasNext()) if (it.next().equals(e)) { it.remove(); @@ -764,94 +769,96 @@ THROWS(IllegalStateException.class, () -> it.remove()); } - checkUnusedElt(s, e);}} + checkUnusedElt(set, e);} }; return randomRemovers[rnd.nextInt(randomRemovers.length)]; } - static void lockStep(NavigableMap m1, - NavigableMap m2) { + static void lockStep(NavigableMap m1, + NavigableMap m2) { if (! (thorough || maybe(3))) return; if (maybe(4)) m1 = serialClone(m1); if (maybe(4)) m2 = serialClone(m2); - List maps = Arrays.asList(m1, m2); - for (NavigableMap m : maps) testEmptyMap(m); + var maps = Arrays.asList(m1, m2); + for (var m : maps) testEmptyMap(m); final Set ints = new HashSet<>(); while (ints.size() < size) ints.add(rnd.nextInt(1024)); final Integer[] elts = ints.toArray(new Integer[size]); + equal(elts.length, size); for (int i = 0; i < size; i++) { MapFrobber adder = randomAdder(m1); - for (final NavigableMap m : maps) { + for (var m : maps) { adder.frob(m); equal(m.size(), i+1); } equalNavigableMaps(m1, m2); } - for (final NavigableMap m : maps) { - final Object e = usedKey(m); + for (var m : maps) { + final var e = usedKey(m); THROWS(IllegalArgumentException.class, - () -> {m.subMap(e,true,e,false) - .subMap(e,true,e,true);}, - () -> {m.subMap(e,false,e,true) - .subMap(e,true,e,true);}, + () -> m.subMap(e,true,e,false).subMap(e,true,e,true), + () -> m.subMap(e,false,e,true).subMap(e,true,e,true), () -> m.tailMap(e,false).tailMap(e,true), - () -> m.headMap(e,false).headMap(e,true)); + () -> m.headMap(e,false).headMap(e,true), + () -> m.headMap(e, false).put(e, 0), + () -> m.tailMap(e, false).putIfAbsent(e, 0), + () -> m.headMap(e, false).computeIfAbsent(e, k -> 1), + () -> m.tailMap(e, false).compute(e, (k, v) -> 0)); } //System.out.printf("%s%n", m1); for (int i = size; i > 0; i--) { MapFrobber remover = randomRemover(m1); - for (final NavigableMap m : maps) { + for (var m : maps) { remover.frob(m); equal(m.size(), i-1); } equalNavigableMaps(m1, m2); } - for (NavigableMap m : maps) testEmptyMap(m); + for (var m : maps) testEmptyMap(m); } - static void lockStep(NavigableSet s1, - NavigableSet s2) { + static void lockStep(NavigableSet s1, + NavigableSet s2) { if (! (thorough || maybe(3))) return; if (maybe(4)) s1 = serialClone(s1); if (maybe(4)) s2 = serialClone(s2); - List sets = Arrays.asList(s1, s2); - for (NavigableSet s : sets) testEmptySet(s); + var sets = Arrays.asList(s1, s2); + for (var s : sets) testEmptySet(s); final Set ints = new HashSet<>(); while (ints.size() < size) ints.add(rnd.nextInt(1024)); final Integer[] elts = ints.toArray(new Integer[size]); + equal(elts.length, size); for (int i = 0; i < size; i++) { SetFrobber adder = randomAdder(s1); - for (final NavigableSet s : sets) { + for (var s : sets) { adder.frob(s); equal(s.size(), i+1); } equalNavigableSets(s1, s2); } - for (final NavigableSet s : sets) { - final Object e = usedElt(s); + for (var s : sets) { + final Integer e = usedElt(s); THROWS(IllegalArgumentException.class, - () -> {s.subSet(e,true,e,false) - .subSet(e,true,e,true);}, - () -> {s.subSet(e,false,e,true) - .subSet(e,true,e,true);}, + () -> s.subSet(e,true,e,false).subSet(e,true,e,true), + () -> s.subSet(e,false,e,true).subSet(e,true,e,true), () -> s.tailSet(e,false).tailSet(e,true), () -> s.headSet(e,false).headSet(e,true)); } //System.out.printf("%s%n", s1); for (int i = size; i > 0; i--) { SetFrobber remover = randomRemover(s1); - for (final NavigableSet s : sets) { + for (var s : sets) { remover.frob(s); equal(s.size(), i-1); } equalNavigableSets(s1, s2); } - for (NavigableSet s : sets) testEmptySet(s); + for (var s : sets) testEmptySet(s); } //--------------------- Infrastructure --------------------------- @@ -862,7 +869,7 @@ static void unexpected(Throwable t) { failed++; t.printStackTrace(); } static void check(boolean cond) { if (cond) pass(); else fail(); } static void equal(Object x, Object y) { - if (x == null ? y == null : x.equals(y)) pass(); + if (Objects.equals(x, y)) pass(); else {System.out.println(x + " not equal to " + y); fail();}} static void equal2(Object x, Object y) {equal(x, y); equal(y, x);} public static void main(String[] args) throws Throwable { --- old/test/micro/org/openjdk/bench/java/util/TreeMapUpdate.java 2020-05-03 07:52:15.844000000 +0000 +++ new/test/micro/org/openjdk/bench/java/util/TreeMapUpdate.java 2020-05-03 07:52:15.504000000 +0000 @@ -39,11 +39,13 @@ import java.util.Collections; import java.util.Comparator; import java.util.Map; +import java.util.NavigableMap; import java.util.Random; import java.util.TreeMap; import java.util.concurrent.TimeUnit; import java.util.function.Function; import java.util.function.Supplier; +import java.util.function.UnaryOperator; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -54,6 +56,9 @@ @Fork(3) @State(Scope.Thread) public class TreeMapUpdate { + @Param({"TreeMap", "descendingMap", "tailMap"}) + public String mode; + @Param({"10", "1000", "100000"}) public int size; @@ -68,10 +73,25 @@ private Supplier> supplier; + private UnaryOperator> transformer; + private Integer[] keys; @Setup public void setUp() { + switch(mode) { + case "TreeMap": + transformer = map -> map; + break; + case "descendingMap": + transformer = map -> map.descendingMap(); + break; + case "tailMap": + transformer = map -> map.tailMap(0, true); + break; + default: + throw new IllegalStateException(mode); + } supplier = comparator ? () -> new TreeMap<>(Comparator.reverseOrder()) : TreeMap::new; keys = IntStream.range(0, size).boxed().toArray(Integer[]::new); Random rnd = seed == 0 ? new Random() : new Random(seed); @@ -86,12 +106,12 @@ @Benchmark public Map baseline() { // Just create map (empty or pre-filled) - return supplier.get(); + return transformer.apply(supplier.get()); } @Benchmark public Map put(Blackhole bh) { - Map map = supplier.get(); + Map map = transformer.apply(supplier.get()); Integer[] keys = this.keys; for (Integer key : keys) { bh.consume(map.put(key, key)); @@ -101,7 +121,7 @@ @Benchmark public Map putIfAbsent(Blackhole bh) { - Map map = supplier.get(); + Map map = transformer.apply(supplier.get()); Integer[] keys = this.keys; for (Integer key : keys) { bh.consume(map.putIfAbsent(key, key)); @@ -111,7 +131,7 @@ @Benchmark public Map computeIfAbsent(Blackhole bh) { - Map map = supplier.get(); + Map map = transformer.apply(supplier.get()); Integer[] keys = this.keys; for (Integer key : keys) { bh.consume(map.computeIfAbsent(key, k -> k)); @@ -121,7 +141,7 @@ @Benchmark public Map compute(Blackhole bh) { - Map map = supplier.get(); + Map map = transformer.apply(supplier.get()); Integer[] keys = this.keys; for (Integer key : keys) { bh.consume(map.compute(key, (k, old) -> k)); @@ -131,7 +151,7 @@ @Benchmark public Map computeIfPresent(Blackhole bh) { - Map map = supplier.get(); + Map map = transformer.apply(supplier.get()); Integer[] keys = this.keys; for (Integer key : keys) { bh.consume(map.computeIfPresent(key, (k, old) -> k)); @@ -141,7 +161,7 @@ @Benchmark public Map merge(Blackhole bh) { - Map map = supplier.get(); + Map map = transformer.apply(supplier.get()); Integer[] keys = this.keys; for (Integer key : keys) { bh.consume(map.merge(key, key, (k1, k2) -> k1));