Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8358081

Fix SequencedMap sequenced view method specifications

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Approved
    • Icon: P4 P4
    • 25
    • core-libs
    • None
    • behavioral
    • low
    • Hide
      Behavior changes mostly affect implementors in that a different code path is followed. In addition, an unmodifiable instead of a possibly-modifiable Map.Entry object can be obtained from the sequencedEntrySet, which can affect users of the sequencedEntrySet. However, modifying map entries this way is rare and obscure, and it's not guaranteed by specification. See comment for compatibility analysis.
      Show
      Behavior changes mostly affect implementors in that a different code path is followed. In addition, an unmodifiable instead of a possibly-modifiable Map.Entry object can be obtained from the sequencedEntrySet, which can affect users of the sequencedEntrySet. However, modifying map entries this way is rare and obscure, and it's not guaranteed by specification. See comment for compatibility analysis.
    • Java API
    • SE

      Summary

      Fix problems with the @implSpec clauses of the collection view methods of SequencedMap.

      Problem

      The SequencedMap interface defines three view collection methods sequencedKeySet(), sequencedValues(), and sequencedEntrySet(). These methods return SequencedCollection or SequencedSet, which is a subtype of SequencedCollection. The @implSpec clauses of these methods' specifications attempt to describe the behavior of the returned object, however, they omit assertions that cover several of the SequencedCollection methods.

      For example, the @implSpec clause of the sequencedKeySet() method describes specific behaviors for the add(), addAll(), and reversed() methods. It then continues, "Each of its other methods calls the corresponding method of the keySet view of this map." The specifications for the sequencedValues() and sequencedEntrySet() methods are similar except that they mention the values view and the entrySet view, respectively.

      The problem is that the six SequencedCollection methods addFirst(), addLast(), getFirst(), getLast(), removeFirst(), and removeLast() seem to be covered by the "other methods" sentence. However, this doesn't make sense, because those methods are not present on the (non-sequenced) keySet, values, and entrySet views.

      What actually happens is that the sequenced view classes inherit the default implementations of these six methods from SequencedCollection. The default implementations' code paths go through the reversed() and iterator() methods as well as additional calls on the returned Iterator. This works from a functional perspective (they perform the correct actions and return the correct results) but the code path is roundabout and we don't want to specify this exact behavior for these methods.

      Solution

      Update the @implSpec clauses of the sequenced view methods to include specifications for the six methods that require improved behavior.

      Specification

      Changes to the java.util.SequencedMap interface specification are shown below.

           /**
            * 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} and {@link
      -     * SequencedSet#addAll addAll} methods throw {@link UnsupportedOperationException}.
      +     * 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() {
      
      
           /**
            * 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} and {@link
      -     * SequencedCollection#addAll addAll} methods throw {@link UnsupportedOperationException}.
      +     * 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() {
      
      
           /**
            * 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} and {@link
      -     * SequencedSet#addAll addAll} methods throw {@link UnsupportedOperationException}.
      +     * 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() {

            smarks Stuart Marks
            smarks Stuart Marks
            Jaikiran Pai
            Votes:
            1 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: