Skip to content

Commit 2b57f40

Browse files
kabutzDoug Lea
authored andcommitted
8343426: ConcurrentSkipListMap.spliterator() can no longer split the stream
Co-authored-by: Doug Lea <[email protected]> Reviewed-by: vklang
1 parent a8152bd commit 2b57f40

File tree

2 files changed

+40
-9
lines changed

2 files changed

+40
-9
lines changed

src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3221,14 +3221,14 @@ public final Comparator<? super K> getComparator() {
32213221
}
32223222
// factory method for KeySpliterator
32233223
final KeySpliterator<K,V> keySpliterator() {
3224-
Index<K,V> h; Node<K,V> n; long est;
3224+
Index<K,V> h; Node<K,V> hn, n; long est;
32253225
VarHandle.acquireFence();
3226-
if ((h = head) == null) {
3226+
if ((h = head) == null || (hn = h.node) == null) {
32273227
n = null;
32283228
est = 0L;
32293229
}
32303230
else {
3231-
n = h.node;
3231+
n = hn.next;
32323232
est = getAdderCount();
32333233
}
32343234
return new KeySpliterator<K,V>(comparator, h, n, null, est);
@@ -3307,14 +3307,14 @@ public int characteristics() {
33073307

33083308
// Almost the same as keySpliterator()
33093309
final ValueSpliterator<K,V> valueSpliterator() {
3310-
Index<K,V> h; Node<K,V> n; long est;
3310+
Index<K,V> h; Node<K,V> hn, n; long est;
33113311
VarHandle.acquireFence();
3312-
if ((h = head) == null) {
3312+
if ((h = head) == null || (hn = h.node) == null) {
33133313
n = null;
33143314
est = 0L;
33153315
}
33163316
else {
3317-
n = h.node;
3317+
n = hn.next;
33183318
est = getAdderCount();
33193319
}
33203320
return new ValueSpliterator<K,V>(comparator, h, n, null, est);
@@ -3411,14 +3411,14 @@ public final Comparator<Map.Entry<K,V>> getComparator() {
34113411

34123412
// Almost the same as keySpliterator()
34133413
final EntrySpliterator<K,V> entrySpliterator() {
3414-
Index<K,V> h; Node<K,V> n; long est;
3414+
Index<K,V> h; Node<K,V> hn, n; long est;
34153415
VarHandle.acquireFence();
3416-
if ((h = head) == null) {
3416+
if ((h = head) == null || (hn = h.node) == null) {
34173417
n = null;
34183418
est = 0L;
34193419
}
34203420
else {
3421-
n = h.node;
3421+
n = hn.next;
34223422
est = getAdderCount();
34233423
}
34243424
return new EntrySpliterator<K,V>(comparator, h, n, null, est);

test/jdk/java/util/concurrent/tck/ConcurrentSkipListMapTest.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1323,6 +1323,37 @@ private int lastAscending() {
13231323
}
13241324
}
13251325

1326+
/**
1327+
* Spliterators.trySplit() returns null with an empty map and non-null when
1328+
* it is not empty.
1329+
*/
1330+
public void testSpliterators() {
1331+
// To test JDK-8343426
1332+
ConcurrentSkipListMap<Integer, Integer> map = new ConcurrentSkipListMap<>();
1333+
for (int i = 1; i <= 1000; i++) map.put(i, i);
1334+
// ensure that the splits do happen
1335+
assertNotNull(map.keySet().spliterator().trySplit());
1336+
assertNotNull(map.entrySet().spliterator().trySplit());
1337+
assertNotNull(map.values().spliterator().trySplit());
1338+
// ensure that the splits return *all* the items in the set
1339+
assertEquals(500_500, map.keySet()
1340+
.parallelStream()
1341+
.mapToInt(Integer::valueOf)
1342+
.sum());
1343+
assertEquals(500_500, map.values()
1344+
.parallelStream()
1345+
.mapToInt(Integer::valueOf)
1346+
.sum());
1347+
assertEquals(500_500 * 2, map.entrySet()
1348+
.parallelStream()
1349+
.mapToInt(entry -> entry.getKey() + entry.getValue())
1350+
.sum());
1351+
map.clear();
1352+
assertNull(map.keySet().spliterator().trySplit());
1353+
assertNull(map.entrySet().spliterator().trySplit());
1354+
assertNull(map.values().spliterator().trySplit());
1355+
}
1356+
13261357
static void assertEq(Item i, int j) {
13271358
if (i == null)
13281359
mustEqual(j, -1);

0 commit comments

Comments
 (0)