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

Add repeat methods to StringBuilder/StringBuffer

    XMLWordPrintable

Details

    • CSR
    • Resolution: Approved
    • P4
    • 21
    • core-libs
    • None
    • source
    • low
    • New methods of final classes, low risk.
    • Java API
    • SE

    Description

      Summary

      Add the ability to repeatedly append char/code point and CharSequence data to StringBuilder/StringBuffer.

      Problem

      Appending a repeated sequence of characters to a StringBuilder is more complicated and inefficient than necessarily.

      Typically, a cumbersome counting loop is required to repeatedly append a sequence.

      Example: Text justification with loop

          static String rightJustify(String str, int width) {
              int padding = Math.max(0, width - str.length());
              StringBuilder sb = new StringBuilder(width);
              for (int i = 0; i < padding; i++) {
                  sb.append(' ');
              }
              return sb.append(str).toString();
          }
      

      String::repeat has been available since JDK 11. Unfortunately use of String::repeat requires the allocation of an intermediary String.

      Example: Text justification with String::repeat

          static String rightJustify(String str, int width) {
              int padding = Math.max(0, width - str.length());
              return new StringBuilder(width)
                  .append(" ".repeat(padding));
                  .append(str)
                  .toString();
          }
      

      Solution

      The proposed solution is to add two methods to the StringBuilder and StringBuffer classes; repeat(int codePoint, int count) and repeat(CharSequence cs, int count).

      Example: Text justification with StringBuilder::repeat

          static String rightJustify(String str, int width) {
              int padding = Math.max(0, width - str.length() ;
              return new StringBuilder(width)
                  .repeat(' ', padding);
                  .append(str);
                  .toString();
          }
      

      The additional benefit is that replication occurs directly in the StringBuilder buffer without any intermediary objects.

      loopRepeatChar         thrpt   25   46507857.247 ±    16001.611  ops/s  for (int i = 0; i < 10; i++) sb.append('*');
      loopRepeatString       thrpt   25   43482336.436 ±   177227.305  ops/s  for (int i = 0; i < 10; i++) sb.append("+-");
      loopRepeatStringUTF16  thrpt   25   40556583.647 ±   365770.314  ops/s  for (int i = 0; i < 10; i++) sb.append("\u2022-");
      
      strRepeatChar          thrpt   25  209038459.568 ±   125055.304  ops/s  sb.append("*".repeat(10));
      strRepeatString        thrpt   25   67675968.232 ±   509906.866  ops/s  sb.append("+-".repeat(10));
      strRepeatStringUTF16   thrpt   25   71712982.352 ±    40114.633  ops/s  sb.append("\u2022-".repeat(10));
      
      sbRepeatChar           thrpt   25  295722073.244 ±   277205.579  ops/s  sb.repeat('*', 10);
      sbRepeatString         thrpt   25   76166442.540 ±  3213215.843  ops/s  sb.repeat("+-", 10);
      sbRepeatStringUTF16    thrpt   25   82658897.156 ±  3971140.701  ops/s  sb.repeat("\u2022-", 10);
      
      sbRepeatStringOneChar  thrpt   25  286870925.029 ± 13221451.039  ops/s  sb.repeat("*", 10);

      Specification

      For StringBuilder:

          /**
           * Repeats {@code count} copies of the string representation of the
           * {@code codePoint} argument to this sequence.
           * <p>
           * The length of this sequence increases by {@code count} times the
           * string representation length.
           * <p>
           * It is usual to use {@code char} expressions for code points. For example:
           * {@snippet lang="java":
           * // insert 10 asterisks into the buffer
           * sb.repeat('*', 10);
           * }
           *
           * @param codePoint  code point to append
           * @param count      number of times to copy
           *
           * @return  a reference to this object.
           *
           * @throws IllegalArgumentException if the specified {@code codePoint}
           * is not a valid Unicode code point or if {@code count} is negative.
           *
           * @since 21
           */
          public StringBuilder repeat(int codePoint, int count) {
      
          /**
           * Appends {@code count} copies of the specified {@code CharSequence} {@code cs}
           * to this sequence.
           * <p>
           * The length of this sequence increases by {@code count} times the
           * {@code CharSequence} length.
           * <p>
           * If {@code cs} is {@code null}, then the four characters
           * {@code "null"} are repeated into this sequence.
           *
           * @param cs     a {@code CharSequence}
           * @param count  number of times to copy
           *
           * @return  a reference to this object.
           *
           * @throws IllegalArgumentException  if {@code count} is negative
           *
           * @since 21
           */
          public StringBuilder repeat(CharSequence cs, int count) {

      For StringBuffer:

          /**
           * Repeats {@code count} copies of the string representation of the
           * {@code codePoint} argument to this sequence.
           * <p>
           * The length of this sequence increases by {@code count} times the
           * string representation length.
           * <p>
           * It is usual to use {@code char} expressions for code points. For example:
           * {@snippet lang="java":
           * // insert 10 asterisks into the buffer
           * sb.repeat('*', 10);
           * }
           *
           * @param codePoint  code point to append
           * @param count      number of times to copy
           *
           * @return  a reference to this object.
           *
           * @throws IllegalArgumentException if the specified {@code codePoint}
           * is not a valid Unicode code point or if {@code count} is negative.
           *
           * @since 21
           */
          public synchronize StringBuffer repeat(int codePoint, int count) {
      
          /**
           * Appends {@code count} copies of the specified {@code CharSequence} {@code cs}
           * to this sequence.
           * <p>
           * The length of this sequence increases by {@code count} times the
           * {@code CharSequence} length.
           * <p>
           * If {@code cs} is {@code null}, then the four characters
           * {@code "null"} are repeated into this sequence.
           *
           * @param cs     a {@code CharSequence}
           * @param count  number of times to copy
           *
           * @return  a reference to this object.
           *
           * @throws IllegalArgumentException  if {@code count} is negative
           *
           * @since 21
           */
          public synchronize StringBuffer repeat(CharSequence cs, int count) {

      Attachments

        Issue Links

          Activity

            People

              jlaskey Jim Laskey
              jlaskey Jim Laskey
              Stuart Marks
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: