mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +02:00
8266571: Sequenced Collections
Reviewed-by: alanb
This commit is contained in:
parent
bad6aa68e4
commit
17ce0976e4
42 changed files with 7060 additions and 150 deletions
|
@ -369,9 +369,15 @@ public class Collections {
|
|||
*
|
||||
* This method runs in linear time.
|
||||
*
|
||||
* @apiNote
|
||||
* This method mutates the specified list in-place. To obtain a
|
||||
* reverse-ordered view of a list without mutating it, use the
|
||||
* {@link List#reversed List.reversed} method.
|
||||
*
|
||||
* @param list the list whose elements are to be reversed.
|
||||
* @throws UnsupportedOperationException if the specified list or
|
||||
* its list-iterator does not support the {@code set} operation.
|
||||
* @see List#reversed List.reversed
|
||||
*/
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public static void reverse(List<?> list) {
|
||||
|
@ -1130,6 +1136,87 @@ public class Collections {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an <a href="Collection.html#unmodview">unmodifiable view</a> of the
|
||||
* specified {@code SequencedCollection}. Query operations on the returned collection
|
||||
* "read through" to the specified collection, and attempts to modify the returned
|
||||
* collection, whether direct or via its iterator, result in an
|
||||
* {@code UnsupportedOperationException}.<p>
|
||||
*
|
||||
* The returned collection does <i>not</i> pass the {@code hashCode} and
|
||||
* {@code equals} operations through to the backing collection, but relies on
|
||||
* {@code Object}'s {@code equals} and {@code hashCode} methods. This
|
||||
* is necessary to preserve the contracts of these operations in the case
|
||||
* that the backing collection is a set or a list.<p>
|
||||
*
|
||||
* The returned collection will be serializable if the specified collection
|
||||
* is serializable.
|
||||
*
|
||||
* @implNote This method may return its argument if the argument is already unmodifiable.
|
||||
* @param <T> the class of the objects in the collection
|
||||
* @param c the collection for which an unmodifiable view is to be
|
||||
* returned.
|
||||
* @return an unmodifiable view of the specified collection.
|
||||
* @since 21
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> SequencedCollection<T> unmodifiableSequencedCollection(SequencedCollection<? extends T> c) {
|
||||
if (c.getClass() == UnmodifiableSequencedCollection.class) {
|
||||
return (SequencedCollection<T>) c;
|
||||
}
|
||||
return new UnmodifiableSequencedCollection<>(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* @serial include
|
||||
*/
|
||||
static class UnmodifiableSequencedCollection<E> extends UnmodifiableCollection<E>
|
||||
implements SequencedCollection<E>, Serializable {
|
||||
|
||||
@java.io.Serial
|
||||
private static final long serialVersionUID = -6060065079711684830L;
|
||||
|
||||
UnmodifiableSequencedCollection(SequencedCollection<? extends E> c) {
|
||||
super(c);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private SequencedCollection<E> sc() {
|
||||
return (SequencedCollection<E>) c;
|
||||
}
|
||||
|
||||
// Even though this wrapper class is serializable, the reversed view is effectively
|
||||
// not serializable because it points to the reversed collection view, which usually isn't
|
||||
// serializable.
|
||||
public SequencedCollection<E> reversed() {
|
||||
return new UnmodifiableSequencedCollection<>(sc().reversed());
|
||||
}
|
||||
|
||||
public void addFirst(E e) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void addLast(E e) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public E getFirst() {
|
||||
return sc().getFirst();
|
||||
}
|
||||
|
||||
public E getLast() {
|
||||
return sc().getLast();
|
||||
}
|
||||
|
||||
public E removeFirst() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public E removeLast() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an <a href="Collection.html#unmodview">unmodifiable view</a> of the
|
||||
* specified set. Query operations on the returned set "read through" to the specified
|
||||
|
@ -1166,6 +1253,56 @@ public class Collections {
|
|||
public int hashCode() {return c.hashCode();}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an <a href="Collection.html#unmodview">unmodifiable view</a> of the
|
||||
* specified {@code SequencedSet}. Query operations on the returned set
|
||||
* "read through" to the specified set, and attempts to modify the returned
|
||||
* set, whether direct or via its iterator, result in an
|
||||
* {@code UnsupportedOperationException}.<p>
|
||||
*
|
||||
* The returned set will be serializable if the specified set
|
||||
* is serializable.
|
||||
*
|
||||
* @implNote This method may return its argument if the argument is already unmodifiable.
|
||||
* @param <T> the class of the objects in the set
|
||||
* @param s the set for which an unmodifiable view is to be returned.
|
||||
* @return an unmodifiable view of the specified sequenced set.
|
||||
* @since 21
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> SequencedSet<T> unmodifiableSequencedSet(SequencedSet<? extends T> s) {
|
||||
// Not checking for subclasses because of heap pollution and information leakage.
|
||||
if (s.getClass() == UnmodifiableSequencedSet.class) {
|
||||
return (SequencedSet<T>) s;
|
||||
}
|
||||
return new UnmodifiableSequencedSet<>(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* @serial include
|
||||
*/
|
||||
static class UnmodifiableSequencedSet<E> extends UnmodifiableSequencedCollection<E>
|
||||
implements SequencedSet<E>, Serializable {
|
||||
@java.io.Serial
|
||||
private static final long serialVersionUID = -2153469532349793522L;
|
||||
|
||||
UnmodifiableSequencedSet(SequencedSet<? extends E> s) {super(s);}
|
||||
public boolean equals(Object o) {return o == this || c.equals(o);}
|
||||
public int hashCode() {return c.hashCode();}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private SequencedSet<E> ss() {
|
||||
return (SequencedSet<E>) c;
|
||||
}
|
||||
|
||||
// Even though this wrapper class is serializable, the reversed view is effectively
|
||||
// not serializable because it points to the reversed set view, which usually isn't
|
||||
// serializable.
|
||||
public SequencedSet<E> reversed() {
|
||||
return new UnmodifiableSequencedSet<>(ss().reversed());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an <a href="Collection.html#unmodview">unmodifiable view</a> of the
|
||||
* specified sorted set. Query operations on the returned sorted set "read
|
||||
|
@ -1504,7 +1641,7 @@ public class Collections {
|
|||
private static final long serialVersionUID = -1034234728574286014L;
|
||||
|
||||
@SuppressWarnings("serial") // Conditionally serializable
|
||||
private final Map<? extends K, ? extends V> m;
|
||||
final Map<? extends K, ? extends V> m;
|
||||
|
||||
UnmodifiableMap(Map<? extends K, ? extends V> m) {
|
||||
if (m==null)
|
||||
|
@ -1828,6 +1965,72 @@ public class Collections {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an <a href="Collection.html#unmodview">unmodifiable view</a> of the
|
||||
* specified {@code SequencedMap}. Query operations on the returned map
|
||||
* "read through" to the specified map, and attempts to modify the returned
|
||||
* map, whether direct or via its collection views, result in an
|
||||
* {@code UnsupportedOperationException}.<p>
|
||||
*
|
||||
* The returned map will be serializable if the specified map
|
||||
* is serializable.
|
||||
*
|
||||
* @implNote This method may return its argument if the argument is already unmodifiable.
|
||||
* @param <K> the class of the map keys
|
||||
* @param <V> the class of the map values
|
||||
* @param m the map for which an unmodifiable view is to be returned.
|
||||
* @return an unmodifiable view of the specified map.
|
||||
* @since 21
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <K,V> SequencedMap<K,V> unmodifiableSequencedMap(SequencedMap<? extends K, ? extends V> m) {
|
||||
// Not checking for subclasses because of heap pollution and information leakage.
|
||||
if (m.getClass() == UnmodifiableSequencedMap.class) {
|
||||
return (SequencedMap<K,V>) m;
|
||||
}
|
||||
return new UnmodifiableSequencedMap<>(m);
|
||||
}
|
||||
|
||||
/**
|
||||
* @serial include
|
||||
*/
|
||||
private static class UnmodifiableSequencedMap<K,V> extends UnmodifiableMap<K,V> implements SequencedMap<K,V>, Serializable {
|
||||
@java.io.Serial
|
||||
private static final long serialVersionUID = -8171676257373950636L;
|
||||
|
||||
UnmodifiableSequencedMap(Map<? extends K, ? extends V> m) {
|
||||
super(m);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private SequencedMap<K, V> sm() {
|
||||
return (SequencedMap<K, V>) m;
|
||||
}
|
||||
|
||||
// Even though this wrapper class is serializable, the reversed view is effectively
|
||||
// not serializable because it points to the reversed map view, which usually isn't
|
||||
// serializable.
|
||||
public SequencedMap<K, V> reversed() {
|
||||
return new UnmodifiableSequencedMap<>(sm().reversed());
|
||||
}
|
||||
|
||||
public Entry<K, V> pollFirstEntry() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public Entry<K, V> pollLastEntry() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public V putFirst(K k, V v) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public V putLast(K k, V v) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an <a href="Collection.html#unmodview">unmodifiable view</a> of the
|
||||
* specified sorted map. Query operations on the returned sorted map "read through"
|
||||
|
@ -5326,6 +5529,14 @@ public class Collections {
|
|||
*
|
||||
* The returned comparator is serializable.
|
||||
*
|
||||
* @apiNote
|
||||
* This method returns a {@code Comparator} that is suitable for sorting
|
||||
* elements in reverse order. To obtain a reverse-ordered <i>view</i> of a
|
||||
* sequenced collection, use the {@link SequencedCollection#reversed
|
||||
* SequencedCollection.reversed} method. Or, to obtain a reverse-ordered
|
||||
* <i>view</i> of a sequenced map, use the {@link SequencedMap#reversed
|
||||
* SequencedMap.reversed} method.
|
||||
*
|
||||
* @param <T> the class of the objects compared by the comparator
|
||||
* @return A comparator that imposes the reverse of the <i>natural
|
||||
* ordering</i> on a collection of objects that implement
|
||||
|
@ -5372,6 +5583,14 @@ public class Collections {
|
|||
* <p>The returned comparator is serializable (assuming the specified
|
||||
* comparator is also serializable or {@code null}).
|
||||
*
|
||||
* @apiNote
|
||||
* This method returns a {@code Comparator} that is suitable for sorting
|
||||
* elements in reverse order. To obtain a reverse-ordered <i>view</i> of a
|
||||
* sequenced collection, use the {@link SequencedCollection#reversed
|
||||
* SequencedCollection.reversed} method. Or, to obtain a reverse-ordered
|
||||
* <i>view</i> of a sequenced map, use the {@link SequencedMap#reversed
|
||||
* SequencedMap.reversed} method.
|
||||
*
|
||||
* @param <T> the class of the objects compared by the comparator
|
||||
* @param cmp a comparator who's ordering is to be reversed by the returned
|
||||
* comparator or {@code null}
|
||||
|
@ -5682,6 +5901,8 @@ public class Collections {
|
|||
* @since 1.6
|
||||
*/
|
||||
public static <E> Set<E> newSetFromMap(Map<E, Boolean> map) {
|
||||
if (! map.isEmpty()) // implicit null check
|
||||
throw new IllegalArgumentException("Map is non-empty");
|
||||
return new SetFromMap<>(map);
|
||||
}
|
||||
|
||||
|
@ -5692,12 +5913,10 @@ public class Collections {
|
|||
implements Set<E>, Serializable
|
||||
{
|
||||
@SuppressWarnings("serial") // Conditionally serializable
|
||||
private final Map<E, Boolean> m; // The backing map
|
||||
final Map<E, Boolean> m; // The backing map
|
||||
private transient Set<E> s; // Its keySet
|
||||
|
||||
SetFromMap(Map<E, Boolean> map) {
|
||||
if (!map.isEmpty())
|
||||
throw new IllegalArgumentException("Map is non-empty");
|
||||
m = map;
|
||||
s = map.keySet();
|
||||
}
|
||||
|
@ -5746,6 +5965,91 @@ public class Collections {
|
|||
stream.defaultReadObject();
|
||||
s = m.keySet();
|
||||
}
|
||||
|
||||
@java.io.Serial
|
||||
private void readObjectNoData() throws java.io.ObjectStreamException {
|
||||
throw new java.io.InvalidObjectException("missing SetFromMap data");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sequenced set backed by the specified map. The resulting set displays
|
||||
* the same ordering, concurrency, and performance characteristics as the
|
||||
* backing map. In essence, this factory method provides a {@link SequencedSet}
|
||||
* implementation corresponding to any {@link SequencedMap} implementation.
|
||||
*
|
||||
* <p>Each method invocation on the set returned by this method results in
|
||||
* exactly one method invocation on the backing map or its {@code keySet}
|
||||
* view, with one exception. The {@code addAll} method is implemented
|
||||
* as a sequence of {@code put} invocations on the backing map.
|
||||
*
|
||||
* <p>The specified map must be empty at the time this method is invoked,
|
||||
* and should not be accessed directly after this method returns. These
|
||||
* conditions are ensured if the map is created empty, passed directly
|
||||
* to this method, and no reference to the map is retained.
|
||||
*
|
||||
* @apiNote
|
||||
* The following example code creates a {@code SequencedSet} from a
|
||||
* {@code LinkedHashMap}. This differs from a {@code LinkedHashSet}
|
||||
* in that the map's {@code removeEldestEntry} is overridden to provide
|
||||
* an eviction policy, which is not possible with a {@code LinkedHashSet}.
|
||||
*
|
||||
* {@snippet :
|
||||
* SequencedSet<String> set = Collections.newSequencedSetFromMap(
|
||||
* new LinkedHashMap<String, Boolean>() {
|
||||
* protected boolean removeEldestEntry(Map.Entry<String, Boolean> e) {
|
||||
* return this.size() > 5;
|
||||
* }
|
||||
* });
|
||||
* }
|
||||
*
|
||||
* @param <E> the class of the map keys and of the objects in the
|
||||
* returned set
|
||||
* @param map the backing map
|
||||
* @return the set backed by the map
|
||||
* @throws IllegalArgumentException if {@code map} is not empty
|
||||
* @since 21
|
||||
*/
|
||||
public static <E> SequencedSet<E> newSequencedSetFromMap(SequencedMap<E, Boolean> map) {
|
||||
if (! map.isEmpty()) // implicit null check
|
||||
throw new IllegalArgumentException("Map is non-empty");
|
||||
return new SequencedSetFromMap<>(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* @serial include
|
||||
*/
|
||||
private static class SequencedSetFromMap<E> extends SetFromMap<E> implements SequencedSet<E> {
|
||||
private E nsee(Map.Entry<E, Boolean> e) {
|
||||
if (e == null) {
|
||||
throw new NoSuchElementException();
|
||||
} else {
|
||||
return e.getKey();
|
||||
}
|
||||
}
|
||||
|
||||
private SequencedMap<E, Boolean> map() {
|
||||
return (SequencedMap<E, Boolean>) super.m;
|
||||
}
|
||||
|
||||
SequencedSetFromMap(SequencedMap<E, Boolean> map) {
|
||||
super(map);
|
||||
}
|
||||
|
||||
// Even though this wrapper class is serializable, the reversed view is effectively
|
||||
// not serializable because it points to the reversed map view, which usually isn't
|
||||
// serializable.
|
||||
public SequencedSet<E> reversed() { return new SequencedSetFromMap<>(map().reversed()); }
|
||||
|
||||
public void addFirst(E e) { map().putFirst(e, Boolean.TRUE); }
|
||||
public void addLast(E e) { map().putLast(e, Boolean.TRUE); }
|
||||
public E getFirst() { return nsee(map().firstEntry()); }
|
||||
public E getLast() { return nsee(map().lastEntry()); }
|
||||
public E removeFirst() { return nsee(map().pollFirstEntry()); }
|
||||
public E removeLast() { return nsee(map().pollLastEntry()); }
|
||||
|
||||
@java.io.Serial
|
||||
private static final long serialVersionUID = -3943479744841433802L;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5761,6 +6065,11 @@ public class Collections {
|
|||
* implemented as a sequence of {@link Deque#addFirst addFirst}
|
||||
* invocations on the backing deque.
|
||||
*
|
||||
* @apiNote
|
||||
* This method provides a view that inverts the sense of certain operations,
|
||||
* but it doesn't reverse the encounter order. To obtain a reverse-ordered
|
||||
* view, use the {@link Deque#reversed Deque.reversed} method.
|
||||
*
|
||||
* @param <T> the class of the objects in the deque
|
||||
* @param deque the deque
|
||||
* @return the queue
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue