| /* | |
| * Copyright (c) 2021, 2025, 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; | |
| import jdk.internal.util.NullableKeyValueHolder; | |
| /** | |
| * 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() ? new NullableKeyValueHolder<>(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() ? new NullableKeyValueHolder<>(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 = new NullableKeyValueHolder<>(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 = new NullableKeyValueHolder<>(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 {@code SequencedSet} view of this map's {@link #keySet keySet}. | |
| * | |
| * @implSpec | |
| * The implementation in this interface returns a {@code SequencedSet} instance | |
| * that behaves as follows. Its {@link SequencedSet#add add}, {@link | |
| * SequencedSet#addAll addAll}, {@link SequencedSet#addFirst addFirst}, and {@link | |
| * SequencedSet#addLast addLast} methods throw {@link UnsupportedOperationException}. | |
| * Its {@link SequencedSet#getFirst getFirst} and {@link SequencedSet#getLast getLast} | |
| * methods are implemented in terms of the {@link #firstEntry firstEntry} and {@link | |
| * #lastEntry lastEntry} methods of this interface, respectively. Its {@link | |
| * SequencedSet#removeFirst removeFirst} and {@link SequencedSet#removeLast removeLast} | |
| * methods are implemented in terms of the {@link #pollFirstEntry pollFirstEntry} and | |
| * {@link #pollLastEntry pollLastEntry} methods of this interface, respectively. | |
| * Its {@link SequencedSet#reversed reversed} method returns the {@link | |
| * #sequencedKeySet sequencedKeySet} view of the {@link #reversed reversed} view of | |
| * this map. Each of its other methods calls the corresponding method of the {@link | |
| * #keySet keySet} view of this map. | |
| * | |
| * @return a {@code SequencedSet} view of this map's {@code keySet} | |
| */ | |
| default SequencedSet<K> sequencedKeySet() { | |
| class SeqKeySet extends AbstractMap.ViewCollection<K> implements SequencedSet<K> { | |
| Collection<K> view() { | |
| return SequencedMap.this.keySet(); | |
| } | |
| public SequencedSet<K> reversed() { | |
| return SequencedMap.this.reversed().sequencedKeySet(); | |
| } | |
| public boolean equals(Object other) { | |
| return view().equals(other); | |
| } | |
| public int hashCode() { | |
| return view().hashCode(); | |
| } | |
| public void addFirst(K k) { throw new UnsupportedOperationException(); } | |
| public void addLast(K k) { throw new UnsupportedOperationException(); } | |
| public K getFirst() { return nsee(SequencedMap.this.firstEntry()).getKey(); } | |
| public K getLast() { return nsee(SequencedMap.this.lastEntry()).getKey(); } | |
| public K removeFirst() { | |
| return nsee(SequencedMap.this.pollFirstEntry()).getKey(); | |
| } | |
| public K removeLast() { | |
| return nsee(SequencedMap.this.pollLastEntry()).getKey(); | |
| } | |
| } | |
| return new SeqKeySet(); | |
| } | |
| /** | |
| * Returns a {@code SequencedCollection} view of this map's {@link #values values} collection. | |
| * | |
| * @implSpec | |
| * The implementation in this interface returns a {@code SequencedCollection} instance | |
| * that behaves as follows. Its {@link SequencedCollection#add add}, {@link | |
| * SequencedCollection#addAll addAll}, {@link SequencedCollection#addFirst addFirst}, and {@link | |
| * SequencedCollection#addLast addLast} methods throw {@link UnsupportedOperationException}. | |
| * Its {@link SequencedCollection#getFirst getFirst} and {@link SequencedCollection#getLast getLast} | |
| * methods are implemented in terms of the {@link #firstEntry firstEntry} and {@link | |
| * #lastEntry lastEntry} methods of this interface, respectively. Its {@link | |
| * SequencedCollection#removeFirst removeFirst} and {@link SequencedCollection#removeLast removeLast} | |
| * methods are implemented in terms of the {@link #pollFirstEntry pollFirstEntry} and | |
| * {@link #pollLastEntry pollLastEntry} methods of this interface, respectively. | |
| * Its {@link SequencedCollection#reversed reversed} method returns the {@link | |
| * #sequencedValues sequencedValues} view of the {@link #reversed reversed} view of | |
| * this map. Its {@link Object#equals equals} and {@link Object#hashCode hashCode} methods | |
| * are inherited from {@link Object}. Each of its other methods calls the corresponding | |
| * method of the {@link #values values} view of this map. | |
| * | |
| * @return a {@code SequencedCollection} view of this map's {@code values} collection | |
| */ | |
| default SequencedCollection<V> sequencedValues() { | |
| class SeqValues extends AbstractMap.ViewCollection<V> implements SequencedCollection<V> { | |
| Collection<V> view() { | |
| return SequencedMap.this.values(); | |
| } | |
| public SequencedCollection<V> reversed() { | |
| return SequencedMap.this.reversed().sequencedValues(); | |
| } | |
| public void addFirst(V v) { throw new UnsupportedOperationException(); } | |
| public void addLast(V v) { throw new UnsupportedOperationException(); } | |
| public V getFirst() { return nsee(SequencedMap.this.firstEntry()).getValue(); } | |
| public V getLast() { return nsee(SequencedMap.this.lastEntry()).getValue(); } | |
| public V removeFirst() { | |
| return nsee(SequencedMap.this.pollFirstEntry()).getValue(); | |
| } | |
| public V removeLast() { | |
| return nsee(SequencedMap.this.pollLastEntry()).getValue(); | |
| } | |
| } | |
| return new SeqValues(); | |
| } | |
| /** | |
| * Returns a {@code SequencedSet} view of this map's {@link #entrySet entrySet}. | |
| * | |
| * @implSpec | |
| * The implementation in this interface returns a {@code SequencedSet} instance | |
| * that behaves as follows. Its {@link SequencedSet#add add}, {@link | |
| * SequencedSet#addAll addAll}, {@link SequencedSet#addFirst addFirst}, and {@link | |
| * SequencedSet#addLast addLast} methods throw {@link UnsupportedOperationException}. | |
| * Its {@link SequencedSet#getFirst getFirst} and {@link SequencedSet#getLast getLast} | |
| * methods are implemented in terms of the {@link #firstEntry firstEntry} and {@link | |
| * #lastEntry lastEntry} methods of this interface, respectively. Its {@link | |
| * SequencedSet#removeFirst removeFirst} and {@link SequencedSet#removeLast removeLast} | |
| * methods are implemented in terms of the {@link #pollFirstEntry pollFirstEntry} and | |
| * {@link #pollLastEntry pollLastEntry} methods of this interface, respectively. | |
| * Its {@link SequencedSet#reversed reversed} method returns the {@link | |
| * #sequencedEntrySet sequencedEntrySet} view of the {@link #reversed reversed} view of | |
| * this map. Each of its other methods calls the corresponding method of the {@link | |
| * #entrySet entrySet} view of this map. | |
| * | |
| * @return a {@code SequencedSet} view of this map's {@code entrySet} | |
| */ | |
| default SequencedSet<Map.Entry<K, V>> sequencedEntrySet() { | |
| class SeqEntrySet extends AbstractMap.ViewCollection<Map.Entry<K, V>> | |
| implements SequencedSet<Map.Entry<K, V>> { | |
| Collection<Map.Entry<K, V>> view() { | |
| return SequencedMap.this.entrySet(); | |
| } | |
| public SequencedSet<Map.Entry<K, V>> reversed() { | |
| return SequencedMap.this.reversed().sequencedEntrySet(); | |
| } | |
| public boolean equals(Object other) { | |
| return view().equals(other); | |
| } | |
| public int hashCode() { | |
| return view().hashCode(); | |
| } | |
| public void addFirst(Map.Entry<K, V> e) { throw new UnsupportedOperationException(); } | |
| public void addLast(Map.Entry<K, V> e) { throw new UnsupportedOperationException(); } | |
| public Map.Entry<K, V> getFirst() { return nsee(SequencedMap.this.firstEntry()); } | |
| public Map.Entry<K, V> getLast() { return nsee(SequencedMap.this.lastEntry()); } | |
| public Map.Entry<K, V> removeFirst() { | |
| return nsee(SequencedMap.this.pollFirstEntry()); | |
| } | |
| public Map.Entry<K, V> removeLast() { | |
| return nsee(SequencedMap.this.pollLastEntry()); | |
| } | |
| } | |
| return new SeqEntrySet(); | |
| } | |
| } |