diff --git a/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java b/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java index 4c2add084ab..1bb36693443 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java @@ -3193,14 +3193,14 @@ public final Comparator getComparator() { } // factory method for KeySpliterator final KeySpliterator keySpliterator() { - Index h; Node n; long est; + Index h; Node hn, n; long est; VarHandle.acquireFence(); - if ((h = head) == null) { + if ((h = head) == null || (hn = h.node) == null) { n = null; est = 0L; } else { - n = h.node; + n = hn.next; est = getAdderCount(); } return new KeySpliterator(comparator, h, n, null, est); @@ -3279,14 +3279,14 @@ public int characteristics() { // Almost the same as keySpliterator() final ValueSpliterator valueSpliterator() { - Index h; Node n; long est; + Index h; Node hn, n; long est; VarHandle.acquireFence(); - if ((h = head) == null) { + if ((h = head) == null || (hn = h.node) == null) { n = null; est = 0L; } else { - n = h.node; + n = hn.next; est = getAdderCount(); } return new ValueSpliterator(comparator, h, n, null, est); @@ -3383,14 +3383,14 @@ public final Comparator> getComparator() { // Almost the same as keySpliterator() final EntrySpliterator entrySpliterator() { - Index h; Node n; long est; + Index h; Node hn, n; long est; VarHandle.acquireFence(); - if ((h = head) == null) { + if ((h = head) == null || (hn = h.node) == null) { n = null; est = 0L; } else { - n = h.node; + n = hn.next; est = getAdderCount(); } return new EntrySpliterator(comparator, h, n, null, est); diff --git a/test/jdk/java/util/concurrent/tck/ConcurrentSkipListMapTest.java b/test/jdk/java/util/concurrent/tck/ConcurrentSkipListMapTest.java index 044f126dd9e..5560b9ed4fe 100644 --- a/test/jdk/java/util/concurrent/tck/ConcurrentSkipListMapTest.java +++ b/test/jdk/java/util/concurrent/tck/ConcurrentSkipListMapTest.java @@ -1323,6 +1323,37 @@ private int lastAscending() { } } + /** + * Spliterators.trySplit() returns null with an empty map and non-null when + * it is not empty. + */ + public void testSpliterators() { + // To test JDK-8343426 + ConcurrentSkipListMap map = new ConcurrentSkipListMap<>(); + for (int i = 1; i <= 1000; i++) map.put(i, i); + // ensure that the splits do happen + assertNotNull(map.keySet().spliterator().trySplit()); + assertNotNull(map.entrySet().spliterator().trySplit()); + assertNotNull(map.values().spliterator().trySplit()); + // ensure that the splits return *all* the items in the set + assertEquals(500_500, map.keySet() + .parallelStream() + .mapToInt(Integer::valueOf) + .sum()); + assertEquals(500_500, map.values() + .parallelStream() + .mapToInt(Integer::valueOf) + .sum()); + assertEquals(500_500 * 2, map.entrySet() + .parallelStream() + .mapToInt(entry -> entry.getKey() + entry.getValue()) + .sum()); + map.clear(); + assertNull(map.keySet().spliterator().trySplit()); + assertNull(map.entrySet().spliterator().trySplit()); + assertNull(map.values().spliterator().trySplit()); + } + static void assertEq(Item i, int j) { if (i == null) mustEqual(j, -1);