mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 07:14:30 +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
331
src/java.base/share/classes/java/util/SequencedMap.java
Normal file
331
src/java.base/share/classes/java/util/SequencedMap.java
Normal file
|
@ -0,0 +1,331 @@
|
|||
/*
|
||||
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.util;
|
||||
|
||||
/**
|
||||
* A Map that has a well-defined encounter order, that supports operations at both ends, and
|
||||
* that is reversible. The <a href="SequencedCollection.html#encounter">encounter order</a>
|
||||
* of a {@code SequencedMap} is similar to that of the elements of a {@link SequencedCollection},
|
||||
* but the ordering applies to mappings instead of individual elements.
|
||||
* <p>
|
||||
* The bulk operations on this map, including the {@link #forEach forEach} and the
|
||||
* {@link #replaceAll replaceAll} methods, operate on this map's mappings in
|
||||
* encounter order.
|
||||
* <p>
|
||||
* The view collections provided by the
|
||||
* {@link #keySet keySet},
|
||||
* {@link #values values},
|
||||
* {@link #entrySet entrySet},
|
||||
* {@link #sequencedKeySet sequencedKeySet},
|
||||
* {@link #sequencedValues sequencedValues},
|
||||
* and
|
||||
* {@link #sequencedEntrySet sequencedEntrySet} methods all reflect the encounter order
|
||||
* of this map. Even though the return values of the {@code keySet}, {@code values}, and
|
||||
* {@code entrySet} methods are not sequenced <i>types</i>, the elements
|
||||
* in those view collections do reflect the encounter order of this map. Thus, the
|
||||
* iterators returned by the statements
|
||||
* {@snippet :
|
||||
* var it1 = sequencedMap.entrySet().iterator();
|
||||
* var it2 = sequencedMap.sequencedEntrySet().iterator();
|
||||
* }
|
||||
* both provide the mappings of {@code sequencedMap} in that map's encounter order.
|
||||
* <p>
|
||||
* This interface provides methods to add mappings, to retrieve mappings, and to remove
|
||||
* mappings at either end of the map's encounter order.
|
||||
* <p>
|
||||
* This interface also defines the {@link #reversed} method, which provides a
|
||||
* reverse-ordered <a href="Collection.html#view">view</a> of this map.
|
||||
* In the reverse-ordered view, the concepts of first and last are inverted, as
|
||||
* are the concepts of successor and predecessor. The first mapping of this map
|
||||
* is the last mapping of the reverse-ordered view, and vice-versa. The successor of some
|
||||
* mapping in this map is its predecessor in the reversed view, and vice-versa. All
|
||||
* methods that respect the encounter order of the map operate as if the encounter order
|
||||
* is inverted. For instance, the {@link #forEach forEach} method of the reversed view reports
|
||||
* the mappings in order from the last mapping of this map to the first. In addition, all of
|
||||
* the view collections of the reversed view also reflect the inverse of this map's
|
||||
* encounter order. For example,
|
||||
* {@snippet :
|
||||
* var itr = sequencedMap.reversed().entrySet().iterator();
|
||||
* }
|
||||
* provides the mappings of this map in the inverse of the encounter order, that is, from
|
||||
* the last mapping to the first mapping. The availability of the {@code reversed} method,
|
||||
* and its impact on the ordering semantics of all applicable methods and views, allow convenient
|
||||
* iteration, searching, copying, and streaming of this map's mappings in either forward order or
|
||||
* reverse order.
|
||||
* <p>
|
||||
* A map's reverse-ordered view is generally not serializable, even if the original
|
||||
* map is serializable.
|
||||
* <p>
|
||||
* The {@link Map.Entry} instances obtained by iterating the {@link #entrySet} view, the
|
||||
* {@link #sequencedEntrySet} view, and its reverse-ordered view, maintain a connection to the
|
||||
* underlying map. This connection is guaranteed only during the iteration. It is unspecified
|
||||
* whether the connection is maintained outside of the iteration. If the underlying map permits
|
||||
* it, calling an Entry's {@link Map.Entry#setValue setValue} method will modify the value of the
|
||||
* underlying mapping. It is, however, unspecified whether modifications to the value in the
|
||||
* underlying mapping are visible in the {@code Entry} instance.
|
||||
* <p>
|
||||
* The methods
|
||||
* {@link #firstEntry},
|
||||
* {@link #lastEntry},
|
||||
* {@link #pollFirstEntry}, and
|
||||
* {@link #pollLastEntry}
|
||||
* return {@link Map.Entry} instances that represent snapshots of mappings as
|
||||
* of the time of the call. They do <em>not</em> support mutation of the
|
||||
* underlying map via the optional {@link Map.Entry#setValue setValue} method.
|
||||
* <p>
|
||||
* Depending upon the implementation, the {@code Entry} instances returned by other
|
||||
* means might or might not be connected to the underlying map. For example, consider
|
||||
* an {@code Entry} obtained in the following manner:
|
||||
* {@snippet :
|
||||
* var entry = sequencedMap.sequencedEntrySet().getFirst();
|
||||
* }
|
||||
* It is not specified by this interface whether the {@code setValue} method of the
|
||||
* {@code Entry} thus obtained will update a mapping in the underlying map, or whether
|
||||
* it will throw an exception, or whether changes to the underlying map are visible in
|
||||
* that {@code Entry}.
|
||||
* <p>
|
||||
* This interface has the same requirements on the {@code equals} and {@code hashCode}
|
||||
* methods as defined by {@link Map#equals Map.equals} and {@link Map#hashCode Map.hashCode}.
|
||||
* Thus, a {@code Map} and a {@code SequencedMap} will compare equals if and only
|
||||
* if they have equal mappings, irrespective of ordering.
|
||||
* <p>
|
||||
* This class is a member of the
|
||||
* <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
|
||||
* Java Collections Framework</a>.
|
||||
*
|
||||
* @param <K> the type of keys maintained by this map
|
||||
* @param <V> the type of mapped values
|
||||
* @since 21
|
||||
*/
|
||||
public interface SequencedMap<K, V> extends Map<K, V> {
|
||||
/**
|
||||
* Returns a reverse-ordered <a href="Collection.html#view">view</a> of this map.
|
||||
* The encounter order of mappings in the returned view is the inverse of the encounter
|
||||
* order of mappings in this map. The reverse ordering affects all order-sensitive operations,
|
||||
* including those on the view collections of the returned view. If the implementation permits
|
||||
* modifications to this view, the modifications "write through" to the underlying map.
|
||||
* Changes to the underlying map might or might not be visible in this reversed view,
|
||||
* depending upon the implementation.
|
||||
*
|
||||
* @return a reverse-ordered view of this map
|
||||
*/
|
||||
SequencedMap<K, V> reversed();
|
||||
|
||||
/**
|
||||
* Returns the first key-value mapping in this map,
|
||||
* or {@code null} if the map is empty.
|
||||
*
|
||||
* @implSpec
|
||||
* The implementation in this interface obtains the iterator of this map's entrySet.
|
||||
* If the iterator has an element, it returns an unmodifiable copy of that element.
|
||||
* Otherwise, it returns null.
|
||||
*
|
||||
* @return the first key-value mapping,
|
||||
* or {@code null} if this map is empty
|
||||
*/
|
||||
default Map.Entry<K,V> firstEntry() {
|
||||
var it = entrySet().iterator();
|
||||
return it.hasNext() ? Map.Entry.copyOf(it.next()) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last key-value mapping in this map,
|
||||
* or {@code null} if the map is empty.
|
||||
*
|
||||
* @implSpec
|
||||
* The implementation in this interface obtains the iterator of the entrySet of this map's
|
||||
* reversed view. If the iterator has an element, it returns an unmodifiable copy of
|
||||
* that element. Otherwise, it returns null.
|
||||
*
|
||||
* @return the last key-value mapping,
|
||||
* or {@code null} if this map is empty
|
||||
*/
|
||||
default Map.Entry<K,V> lastEntry() {
|
||||
var it = reversed().entrySet().iterator();
|
||||
return it.hasNext() ? Map.Entry.copyOf(it.next()) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes and returns the first key-value mapping in this map,
|
||||
* or {@code null} if the map is empty (optional operation).
|
||||
*
|
||||
* @implSpec
|
||||
* The implementation in this interface obtains the iterator of this map's entrySet.
|
||||
* If the iterator has an element, it calls {@code remove} on the iterator and
|
||||
* then returns an unmodifiable copy of that element. Otherwise, it returns null.
|
||||
*
|
||||
* @return the removed first entry of this map,
|
||||
* or {@code null} if this map is empty
|
||||
* @throws UnsupportedOperationException if this collection implementation does not
|
||||
* support this operation
|
||||
*/
|
||||
default Map.Entry<K,V> pollFirstEntry() {
|
||||
var it = entrySet().iterator();
|
||||
if (it.hasNext()) {
|
||||
var entry = Map.Entry.copyOf(it.next());
|
||||
it.remove();
|
||||
return entry;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes and returns the last key-value mapping in this map,
|
||||
* or {@code null} if the map is empty (optional operation).
|
||||
*
|
||||
* @implSpec
|
||||
* The implementation in this interface obtains the iterator of the entrySet of this map's
|
||||
* reversed view. If the iterator has an element, it calls {@code remove} on the iterator
|
||||
* and then returns an unmodifiable copy of that element. Otherwise, it returns null.
|
||||
*
|
||||
* @return the removed last entry of this map,
|
||||
* or {@code null} if this map is empty
|
||||
* @throws UnsupportedOperationException if this collection implementation does not
|
||||
* support this operation
|
||||
*/
|
||||
default Map.Entry<K,V> pollLastEntry() {
|
||||
var it = reversed().entrySet().iterator();
|
||||
if (it.hasNext()) {
|
||||
var entry = Map.Entry.copyOf(it.next());
|
||||
it.remove();
|
||||
return entry;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the given mapping into the map if it is not already present, or replaces the
|
||||
* value of a mapping if it is already present (optional operation). After this operation
|
||||
* completes normally, the given mapping will be present in this map, and it will be the
|
||||
* first mapping in this map's encounter order.
|
||||
*
|
||||
* @implSpec The implementation in this interface always throws
|
||||
* {@code UnsupportedOperationException}.
|
||||
*
|
||||
* @param k the key
|
||||
* @param v the value
|
||||
* @return the value previously associated with k, or null if none
|
||||
* @throws UnsupportedOperationException if this collection implementation does not
|
||||
* support this operation
|
||||
*/
|
||||
default V putFirst(K k, V v) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the given mapping into the map if it is not already present, or replaces the
|
||||
* value of a mapping if it is already present (optional operation). After this operation
|
||||
* completes normally, the given mapping will be present in this map, and it will be the
|
||||
* last mapping in this map's encounter order.
|
||||
*
|
||||
* @implSpec The implementation in this interface always throws
|
||||
* {@code UnsupportedOperationException}.
|
||||
*
|
||||
* @param k the key
|
||||
* @param v the value
|
||||
* @return the value previously associated with k, or null if none
|
||||
* @throws UnsupportedOperationException if this collection implementation does not
|
||||
* support this operation
|
||||
*/
|
||||
default V putLast(K k, V v) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link SequencedSet} view of this map's keySet.
|
||||
*
|
||||
* @implSpec
|
||||
* The implementation in this interface returns a {@code SequencedSet}
|
||||
* implementation that delegates all operations either to this map or to this map's
|
||||
* {@link #keySet}, except for its {@link SequencedSet#reversed reversed} method,
|
||||
* which instead returns the result of calling {@code sequencedKeySet} on this map's
|
||||
* reverse-ordered view.
|
||||
*
|
||||
* @return a SequencedSet view of this map's keySet
|
||||
*/
|
||||
default SequencedSet<K> sequencedKeySet() {
|
||||
class SeqKeySet extends AbstractMap.ViewCollection<K> implements SequencedSet<K> {
|
||||
SeqKeySet() {
|
||||
super(SequencedMap.this.keySet());
|
||||
}
|
||||
public SequencedSet<K> reversed() {
|
||||
return SequencedMap.this.reversed().sequencedKeySet();
|
||||
}
|
||||
}
|
||||
return new SeqKeySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link SequencedCollection} view of this map's values collection.
|
||||
*
|
||||
* @implSpec
|
||||
* The implementation in this interface returns a {@code SequencedCollection}
|
||||
* implementation that delegates all operations either to this map or to this map's
|
||||
* {@link #values} collection, except for its {@link SequencedCollection#reversed reversed}
|
||||
* method, which instead returns the result of calling {@code sequencedValues} on this map's
|
||||
* reverse-ordered view.
|
||||
*
|
||||
* @return a SequencedCollection view of this map's values collection
|
||||
*/
|
||||
default SequencedCollection<V> sequencedValues() {
|
||||
class SeqValues extends AbstractMap.ViewCollection<V> implements SequencedCollection<V> {
|
||||
SeqValues() {
|
||||
super(SequencedMap.this.values());
|
||||
}
|
||||
public SequencedCollection<V> reversed() {
|
||||
return SequencedMap.this.reversed().sequencedValues();
|
||||
}
|
||||
}
|
||||
return new SeqValues();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link SequencedSet} view of this map's entrySet.
|
||||
*
|
||||
* @implSpec
|
||||
* The implementation in this interface returns a {@code SequencedSet}
|
||||
* implementation that delegates all operations either to this map or to this map's
|
||||
* {@link #entrySet}, except for its {@link SequencedSet#reversed reversed} method,
|
||||
* which instead returns the result of calling {@code sequencedEntrySet} on this map's
|
||||
* reverse-ordered view.
|
||||
*
|
||||
* @return a SequencedSet view of this map's entrySet
|
||||
*/
|
||||
default SequencedSet<Map.Entry<K, V>> sequencedEntrySet() {
|
||||
class SeqEntrySet extends AbstractMap.ViewCollection<Map.Entry<K, V>>
|
||||
implements SequencedSet<Map.Entry<K, V>> {
|
||||
SeqEntrySet() {
|
||||
super(SequencedMap.this.entrySet());
|
||||
}
|
||||
public SequencedSet<Map.Entry<K, V>> reversed() {
|
||||
return SequencedMap.this.reversed().sequencedEntrySet();
|
||||
}
|
||||
}
|
||||
return new SeqEntrySet();
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue