Skip to content

Commit ef47635

Browse files
author
Stuart Marks
committed
8358015: Fix SequencedMap sequenced view method specifications
Reviewed-by: jpai, bchristi
1 parent c909216 commit ef47635

File tree

3 files changed

+71
-12
lines changed

3 files changed

+71
-12
lines changed

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -877,6 +877,14 @@ public String toString() {
877877
*/
878878
/* non-public */ abstract static class ViewCollection<E> implements Collection<E> {
879879
UnsupportedOperationException uoe() { return new UnsupportedOperationException(); }
880+
// convert null entry return values into NSEE
881+
static <T extends Map.Entry<?,?>> T nsee(T entry) {
882+
if (entry == null) {
883+
throw new NoSuchElementException();
884+
} else {
885+
return entry;
886+
}
887+
}
880888
abstract Collection<E> view();
881889

882890
public boolean add(E t) { throw uoe(); }

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

Lines changed: 58 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -263,8 +263,15 @@ default V putLast(K k, V v) {
263263
*
264264
* @implSpec
265265
* The implementation in this interface returns a {@code SequencedSet} instance
266-
* that behaves as follows. Its {@link SequencedSet#add add} and {@link
267-
* SequencedSet#addAll addAll} methods throw {@link UnsupportedOperationException}.
266+
* that behaves as follows. Its {@link SequencedSet#add add}, {@link
267+
* SequencedSet#addAll addAll}, {@link SequencedSet#addFirst addFirst}, and {@link
268+
* SequencedSet#addLast addLast} methods throw {@link UnsupportedOperationException}.
269+
* Its {@link SequencedSet#getFirst getFirst} and {@link SequencedSet#getLast getLast}
270+
* methods are implemented in terms of the {@link #firstEntry firstEntry} and {@link
271+
* #lastEntry lastEntry} methods of this interface, respectively. Its {@link
272+
* SequencedSet#removeFirst removeFirst} and {@link SequencedSet#removeLast removeLast}
273+
* methods are implemented in terms of the {@link #pollFirstEntry pollFirstEntry} and
274+
* {@link #pollLastEntry pollLastEntry} methods of this interface, respectively.
268275
* Its {@link SequencedSet#reversed reversed} method returns the {@link
269276
* #sequencedKeySet sequencedKeySet} view of the {@link #reversed reversed} view of
270277
* this map. Each of its other methods calls the corresponding method of the {@link
@@ -286,6 +293,16 @@ public boolean equals(Object other) {
286293
public int hashCode() {
287294
return view().hashCode();
288295
}
296+
public void addFirst(K k) { throw new UnsupportedOperationException(); }
297+
public void addLast(K k) { throw new UnsupportedOperationException(); }
298+
public K getFirst() { return nsee(SequencedMap.this.firstEntry()).getKey(); }
299+
public K getLast() { return nsee(SequencedMap.this.lastEntry()).getKey(); }
300+
public K removeFirst() {
301+
return nsee(SequencedMap.this.pollFirstEntry()).getKey();
302+
}
303+
public K removeLast() {
304+
return nsee(SequencedMap.this.pollLastEntry()).getKey();
305+
}
289306
}
290307
return new SeqKeySet();
291308
}
@@ -295,8 +312,15 @@ public int hashCode() {
295312
*
296313
* @implSpec
297314
* The implementation in this interface returns a {@code SequencedCollection} instance
298-
* that behaves as follows. Its {@link SequencedCollection#add add} and {@link
299-
* SequencedCollection#addAll addAll} methods throw {@link UnsupportedOperationException}.
315+
* that behaves as follows. Its {@link SequencedCollection#add add}, {@link
316+
* SequencedCollection#addAll addAll}, {@link SequencedCollection#addFirst addFirst}, and {@link
317+
* SequencedCollection#addLast addLast} methods throw {@link UnsupportedOperationException}.
318+
* Its {@link SequencedCollection#getFirst getFirst} and {@link SequencedCollection#getLast getLast}
319+
* methods are implemented in terms of the {@link #firstEntry firstEntry} and {@link
320+
* #lastEntry lastEntry} methods of this interface, respectively. Its {@link
321+
* SequencedCollection#removeFirst removeFirst} and {@link SequencedCollection#removeLast removeLast}
322+
* methods are implemented in terms of the {@link #pollFirstEntry pollFirstEntry} and
323+
* {@link #pollLastEntry pollLastEntry} methods of this interface, respectively.
300324
* Its {@link SequencedCollection#reversed reversed} method returns the {@link
301325
* #sequencedValues sequencedValues} view of the {@link #reversed reversed} view of
302326
* this map. Its {@link Object#equals equals} and {@link Object#hashCode hashCode} methods
@@ -313,6 +337,16 @@ Collection<V> view() {
313337
public SequencedCollection<V> reversed() {
314338
return SequencedMap.this.reversed().sequencedValues();
315339
}
340+
public void addFirst(V v) { throw new UnsupportedOperationException(); }
341+
public void addLast(V v) { throw new UnsupportedOperationException(); }
342+
public V getFirst() { return nsee(SequencedMap.this.firstEntry()).getValue(); }
343+
public V getLast() { return nsee(SequencedMap.this.lastEntry()).getValue(); }
344+
public V removeFirst() {
345+
return nsee(SequencedMap.this.pollFirstEntry()).getValue();
346+
}
347+
public V removeLast() {
348+
return nsee(SequencedMap.this.pollLastEntry()).getValue();
349+
}
316350
}
317351
return new SeqValues();
318352
}
@@ -322,8 +356,15 @@ public SequencedCollection<V> reversed() {
322356
*
323357
* @implSpec
324358
* The implementation in this interface returns a {@code SequencedSet} instance
325-
* that behaves as follows. Its {@link SequencedSet#add add} and {@link
326-
* SequencedSet#addAll addAll} methods throw {@link UnsupportedOperationException}.
359+
* that behaves as follows. Its {@link SequencedSet#add add}, {@link
360+
* SequencedSet#addAll addAll}, {@link SequencedSet#addFirst addFirst}, and {@link
361+
* SequencedSet#addLast addLast} methods throw {@link UnsupportedOperationException}.
362+
* Its {@link SequencedSet#getFirst getFirst} and {@link SequencedSet#getLast getLast}
363+
* methods are implemented in terms of the {@link #firstEntry firstEntry} and {@link
364+
* #lastEntry lastEntry} methods of this interface, respectively. Its {@link
365+
* SequencedSet#removeFirst removeFirst} and {@link SequencedSet#removeLast removeLast}
366+
* methods are implemented in terms of the {@link #pollFirstEntry pollFirstEntry} and
367+
* {@link #pollLastEntry pollLastEntry} methods of this interface, respectively.
327368
* Its {@link SequencedSet#reversed reversed} method returns the {@link
328369
* #sequencedEntrySet sequencedEntrySet} view of the {@link #reversed reversed} view of
329370
* this map. Each of its other methods calls the corresponding method of the {@link
@@ -346,6 +387,16 @@ public boolean equals(Object other) {
346387
public int hashCode() {
347388
return view().hashCode();
348389
}
390+
public void addFirst(Map.Entry<K, V> e) { throw new UnsupportedOperationException(); }
391+
public void addLast(Map.Entry<K, V> e) { throw new UnsupportedOperationException(); }
392+
public Map.Entry<K, V> getFirst() { return nsee(SequencedMap.this.firstEntry()); }
393+
public Map.Entry<K, V> getLast() { return nsee(SequencedMap.this.lastEntry()); }
394+
public Map.Entry<K, V> removeFirst() {
395+
return nsee(SequencedMap.this.pollFirstEntry());
396+
}
397+
public Map.Entry<K, V> removeLast() {
398+
return nsee(SequencedMap.this.pollLastEntry());
399+
}
349400
}
350401
return new SeqEntrySet();
351402
}

test/jdk/java/util/SequencedCollection/BasicMap.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -563,12 +563,12 @@ public void checkChecked(SequencedMap<String, Integer> map) {
563563
SequencedMap<Object, Object> objMap = (SequencedMap<Object, Object>)(SequencedMap)map;
564564
assertThrows(CCE, () -> { objMap.put(new Object(), 99); });
565565
assertThrows(CCE, () -> { objMap.put("x", new Object()); });
566-
assertThrows(CCE, () -> { objMap.sequencedEntrySet().getFirst().setValue(new Object()); });
567-
assertThrows(CCE, () -> { objMap.sequencedEntrySet().reversed().getFirst().setValue(new Object()); });
566+
assertThrows(CCE, () -> { objMap.sequencedEntrySet().iterator().next().setValue(new Object()); });
567+
assertThrows(CCE, () -> { objMap.sequencedEntrySet().reversed().iterator().next().setValue(new Object()); });
568568
assertThrows(CCE, () -> { objMap.reversed().put(new Object(), 99); });
569569
assertThrows(CCE, () -> { objMap.reversed().put("x", new Object()); });
570-
assertThrows(CCE, () -> { objMap.reversed().sequencedEntrySet().getFirst().setValue(new Object()); });
571-
assertThrows(CCE, () -> { objMap.reversed().sequencedEntrySet().reversed().getFirst().setValue(new Object()); });
570+
assertThrows(CCE, () -> { objMap.reversed().sequencedEntrySet().iterator().next().setValue(new Object()); });
571+
assertThrows(CCE, () -> { objMap.reversed().sequencedEntrySet().reversed().iterator().next().setValue(new Object()); });
572572
}
573573

574574
public void checkEntry(Map.Entry<String, Integer> entry, String key, Integer value) {

0 commit comments

Comments
 (0)