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

Optimize HashMap.keySet()/HashMap.values()/HashSet toArray() methods

    XMLWordPrintable

    Details

    • Type: CSR
    • Status: Closed
    • Priority: P4
    • Resolution: Approved
    • Fix Version/s: 14
    • Component/s: core-libs
    • Labels:
      None
    • Subcomponent:
    • Compatibility Kind:
      behavioral
    • Compatibility Risk:
      low
    • Compatibility Risk Description:
      Hide
      The following code sample illustrates the behavioral change:

      import java.util.*;

      class Example extends HashSet<String> {
        public Iterator<String> iterator() {
          add("(default)");
          return super.iterator();
        }

        public static void main(String[] args) {
          System.out.println(Arrays.toString(new Example().toArray()));
        }
      }

      Without applying the patch it outputs `[(default)]` as code author relies on implicit call of `iterator()` inside `toArray()`. After the patch is applied it outputs `[]`.
      Show
      The following code sample illustrates the behavioral change: import java.util.*; class Example extends HashSet<String> {   public Iterator<String> iterator() {     add("(default)");     return super.iterator();   }   public static void main(String[] args) {     System.out.println(Arrays.toString(new Example().toArray()));   } } Without applying the patch it outputs `[(default)]` as code author relies on implicit call of `iterator()` inside `toArray()`. After the patch is applied it outputs `[]`.
    • Interface Kind:
      Java API
    • Scope:
      Implementation

      Description

      Summary

      The toArray() implementations in HashSet, HashMap.keySet(), HashMap.values(), LinkedHashSet, LinkedHashMap.keySet() and LinkedHashMap.values() will no longer delegate to iterator().

      Problem

      Currently the toArray() methods of HashSet, HashMap.keySet(), HashMap.values(), LinkedHashSet, LinkedHashMap.keySet() and LinkedHashMap.values() are inherited from AbstractCollection::toArray which creates an iterator(). This is unnecessarily expensive, as it maintains extra state in its fields and checks modCount after every element.

      Solution

      An optimization is proposed to manually implement toArray() methods of HashSet, HashMap.keySet(), HashMap.values(), LinkedHashSet, LinkedHashMap.keySet() and LinkedHashMap.values(), rather than inherit a less efficient implementation from AbstractCollection. As a result toArray() method won't create an iterator() anymore which may slightly affect the behavior. This is especially important for HashSet and LinkedHashSet which could be extended by users. For example, the user might subclass HashSet, override an iterator() method adding some custom logic and expect that this custom logic will be executed by toArray().

      Specification

      No specification change; behavioral change only.

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              tvaleev Tagir Valeev
              Reporter:
              tvaleev Tagir Valeev
              Reviewed By:
              Stuart Marks
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved: