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

Add Collections.shuffle overload that accepts RandomGenerator interface

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Approved
    • Icon: P4 P4
    • 21
    • core-libs
    • None
    • source
    • minimal
    • Adding new static method to library class poses a negligible compatibility risk.
    • Java API
    • SE

      Summary

      Collections.shuffle(List, RandomGenerator) static method is added to be able to conveniently shuffle lists using RandomGenerator interface.

      Problem

      Java 17 added RandomGenerator interface. However, existing method Collections.shuffle accepts old java.util.Random class. While since Java 19, it's possible to use Random.from(RandomGenerator) wrapper, it would be more convenient to provide direct overload shuffle(List list, RandomGenerator rnd).

      Solution

      An overload to Collections.shuffle is created that accepts RandomGenerator interface. Its specification is basically the same, as the specification for existing Collections.shuffle(List, Random).

      Specification

      The specification for new method shuffle(List, RandomGenerator) should be the following (mostly a copy of previous specification of shuffle(List, Random)):

          /**
           * Randomly permute the specified list using the specified source of
           * randomness.  All permutations occur with equal likelihood
           * assuming that the source of randomness is fair.<p>
           *
           * This implementation traverses the list backwards, from the last element
           * up to the second, repeatedly swapping a randomly selected element into
           * the "current position".  Elements are randomly selected from the
           * portion of the list that runs from the first element to the current
           * position, inclusive.<p>
           *
           * @implSpec This method runs in linear time.  If the specified list does not
           * implement the {@link RandomAccess} interface and is large, this
           * implementation dumps the specified list into an array before shuffling
           * it, and dumps the shuffled array back into the list.  This avoids the
           * quadratic behavior that would result from shuffling a "sequential
           * access" list in place.
           *
           * @param  list the list to be shuffled.
           * @param  rnd the source of randomness to use to shuffle the list.
           * @throws UnsupportedOperationException if the specified list or its
           *         list-iterator does not support the {@code set} operation.
           * @since 21
           */
          public static void shuffle(List<?> list, RandomGenerator rnd) {...}

      Also, the specification of existing shuffle(List, Random) should be updated to reduce the repetition and recommend the new method:

          /**
           * Randomly permute the specified list using the specified source of
           * randomness.<p>
           *
           * This method is equivalent to {@link #shuffle(List, RandomGenerator)}
           * and exists for backward compatibility. The {@link #shuffle(List, RandomGenerator)}
           * method is preferred, as it is not limited to random generators
           * that extend the {@link Random} class.
           *
           * @param  list the list to be shuffled.
           * @param  rnd the source of randomness to use to shuffle the list.
           * @throws UnsupportedOperationException if the specified list or its
           *         list-iterator does not support the {@code set} operation.
           */
          public static void shuffle(List<?> list, Random rnd) {...}

      And finally, the specification of the shuffle(List<?> list) is also updated to use an @implSpec tag to specify its implementation properties.

      --- a/src/java.base/share/classes/java/util/Collections.java
      +++ b/src/java.base/share/classes/java/util/Collections.java
      @@ -411,7 +411,7 @@ public class Collections {
            * portion of the list that runs from the first element to the current
            * position, inclusive.
            *
      -     * <p>This method runs in linear time.  If the specified list does not
      +     * @implSpec This method runs in linear time.  If the specified list does not
            * implement the {@link RandomAccess} interface and is large, this
            * implementation dumps the specified list into an array before shuffling
            * it, and dumps the shuffled array back into the list.  This avoids the

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

              Created:
              Updated:
              Resolved: