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

Add getChars(int, int, char[], int) to CharSequence and CharBuffer

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Approved
    • Icon: P4 P4
    • 25
    • core-libs
    • None
    • medium
    • Hide
      CharSequence::isEmpty is a reminder that adding a default method to an interface is potentially source and binary incompatibility. It's possible that there are CharSequence implementations that implement this method but with a non-void return. However, given that String, StringBuffer and StringBuilder implement this interface then it seems unlikely so the compatibility risk of adding this method is not high.

      A cross-repository Github analysis has proven this claim: Of over 100 identified implementations of getChars(int, int, char[], int) not a single one was found which would fail to work due to the proposed API, and only one single class was found which actually implemented the same signature with different semantics, but only as an internally used class, hence having no effect.
      Show
      CharSequence::isEmpty is a reminder that adding a default method to an interface is potentially source and binary incompatibility. It's possible that there are CharSequence implementations that implement this method but with a non-void return. However, given that String, StringBuffer and StringBuilder implement this interface then it seems unlikely so the compatibility risk of adding this method is not high. A cross-repository Github analysis has proven this claim: Of over 100 identified implementations of getChars(int, int, char[], int) not a single one was found which would fail to work due to the proposed API, and only one single class was found which actually implemented the same signature with different semantics, but only as an internally used class, hence having no effect.
    • Java API
    • SE

      Summary

      New method CharSequence.getChars(int, int, char[], int) on java.lang.CharSequence to bulk-read characters from a region in the CharSequence into a region of the provided char[].

      Problem

      CharSequence interface does not provide a bulk-read facility. Some CharSequence implementations do not support bulk-reading at all, while others (like String and CharBuffer) do support bulk-reading but do not share a common method signature to perform it.

      Applications wanting to bulk-read from CharSequence must contain a (theoretically infinite) list of bulk-reading solutions, e. g. (copied from Reader.of(CharSequence) in JDK 24):

      switch (cs) {
          case String s -> s.getChars(next, next + n, cbuf, off);
          case StringBuilder sb -> sb.getChars(next, next + n, cbuf, off);
          case StringBuffer sb -> sb.getChars(next, next + n, cbuf, off);
          case CharBuffer cb -> cb.get(next, cbuf, off, n);
          default -> {
              for (int i = 0; i < n; i++)
                  cbuf[off + i] = cs.charAt(next + i);
          }
      }

      The motivation for the new method is performance as sequential reading is expensive.

      Solution

      Add a new method public void getChars(int, int, char[], int) to CharSequence and CharBuffer.

      Specification

      String:

      /**
       * {@inheritDoc CharSequence}
       * @param srcBegin {@inheritDoc CharSequence}
       * @param srcEnd   {@inheritDoc CharSequence}
       * @param dst      {@inheritDoc CharSequence}
       * @param dstBegin {@inheritDoc CharSequence}
       * @throws IndexOutOfBoundsException {@inheritDoc CharSequence}
       */
      public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)

      StringBuffer and StringBuilder:

      /**
       * {@inheritDoc CharSequence}
       */
      public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)

      CharSequence:

      /**
       * Copies characters from this sequence into the given destination array.
       * The first character to be copied is at index {@code srcBegin}; the last
       * character to be copied is at index {@code srcEnd-1}. The total number of
       * characters to be copied is {@code srcEnd-srcBegin}. The
       * characters are copied into the subarray of {@code dst} starting
       * at index {@code dstBegin} and ending at index:
       * <pre>{@code
       * dstbegin + (srcEnd-srcBegin) - 1
       * }</pre>
       *
       * @param      srcBegin   start copying at this offset.
       * @param      srcEnd     stop copying at this offset.
       * @param      dst        the array to copy the data into.
       * @param      dstBegin   offset into {@code dst}.
       * @throws     IndexOutOfBoundsException  if any of the following is true:
       *             <ul>
       *             <li>{@code srcBegin} is negative
       *             <li>{@code dstBegin} is negative
       *             <li>the {@code srcBegin} argument is greater than
       *             the {@code srcEnd} argument.
       *             <li>{@code srcEnd} is greater than
       *             {@code this.length()}.
       *             <li>{@code dstBegin+srcEnd-srcBegin} is greater than
       *             {@code dst.length}
       *             </ul>
       * @throws     NullPointerException if {@code dst} is {@code null}
       *
       * @implSpec
       * The default implementation invokes {@link #charAt(int index)} in a loop
       * iterating {@code index} from {@code srcBegin} to {@code srcEnd-1}.
       * Concurrent truncation of this character sequence can throw
       * {@code IndexOutOfBoundsException}. In this case, some characters, but not
       * all, may be already transferred.
       *
       * @since 25
       */
      public default void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)

      CharBuffer:

      /**
       * Absolute bulk <i>get</i> method.
       *
       * <p> This method transfers {@code srcEnd-srcBegin} characters from this
       * buffer into the given array, starting at index {@code srcBegin} in this
       * buffer and at offset {@code dstBegin} in the array. The position of this
       * buffer is unchanged.
       *
       * @param  srcBegin
       *         The index in this buffer from which the first character will be
       *         read; must be non-negative and less than {@code limit()}
       *
       * @param  srcEnd
       *         The index in this buffer directly before the last character to
       *         read; must be non-negative and less or equal than {@code limit()}
       *         and must be greater or equal than {@code srcBegin}
       *
       * @param  dst
       *         The destination array
       *
       * @param  dstBegin
       *         The offset within the array of the first character to be
       *         written; must be non-negative and less than {@code dst.length}
       *
       * @throws  IndexOutOfBoundsException
       *          If the preconditions on the {@code srcBegin}, {@code srcEnd},
       *          and {@code dstBegin} parameters do not hold
       *
       * @implSpec This method is equivalent to
       *           {@code get(srcBegin, dst, dstBegin, srcEnd - srcBegin)}.
       *
       * @since 25
       */
      @Override
      public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)

            mkarg Markus Karg
            mkarg Markus Karg
            Alan Bateman, Chen Liang, Jaikiran Pai
            Votes:
            0 Vote for this issue
            Watchers:
            6 Start watching this issue

              Created:
              Updated:
              Resolved: