jdk/src/java.base/share/classes/java/util/StringJoiner.java
author mchung
Fri, 22 May 2015 16:43:39 -0700
changeset 30789 9eca83469588
parent 25991 e48157b42439
child 32834 e1dca5fe4de3
permissions -rw-r--r--
8074431: Remove native2ascii tool Reviewed-by: erikj, alanb, okutsu, mfang, naoto
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
17181
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
     1
/*
25967
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
     2
 * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
17181
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
     4
 *
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    10
 *
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    15
 * accompanied this code).
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    16
 *
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    20
 *
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    23
 * questions.
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    24
 */
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    25
package java.util;
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    26
25967
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
    27
import sun.misc.JavaLangAccess;
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
    28
import sun.misc.SharedSecrets;
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
    29
17181
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    30
/**
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    31
 * {@code StringJoiner} is used to construct a sequence of characters separated
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    32
 * by a delimiter and optionally starting with a supplied prefix
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    33
 * and ending with a supplied suffix.
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    34
 * <p>
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    35
 * Prior to adding something to the {@code StringJoiner}, its
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    36
 * {@code sj.toString()} method will, by default, return {@code prefix + suffix}.
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    37
 * However, if the {@code setEmptyValue} method is called, the {@code emptyValue}
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    38
 * supplied will be returned instead. This can be used, for example, when
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    39
 * creating a string using set notation to indicate an empty set, i.e.
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    40
 * <code>"{}"</code>, where the {@code prefix} is <code>"{"</code>, the
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    41
 * {@code suffix} is <code>"}"</code> and nothing has been added to the
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    42
 * {@code StringJoiner}.
17934
4045b37aef13 8014383: StringJoiner example in class description not in sync with streams API
psandoz
parents: 17333
diff changeset
    43
 *
4045b37aef13 8014383: StringJoiner example in class description not in sync with streams API
psandoz
parents: 17333
diff changeset
    44
 * @apiNote
4045b37aef13 8014383: StringJoiner example in class description not in sync with streams API
psandoz
parents: 17333
diff changeset
    45
 * <p>The String {@code "[George:Sally:Fred]"} may be constructed as follows:
17181
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    46
 *
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    47
 * <pre> {@code
17934
4045b37aef13 8014383: StringJoiner example in class description not in sync with streams API
psandoz
parents: 17333
diff changeset
    48
 * StringJoiner sj = new StringJoiner(":", "[", "]");
4045b37aef13 8014383: StringJoiner example in class description not in sync with streams API
psandoz
parents: 17333
diff changeset
    49
 * sj.add("George").add("Sally").add("Fred");
4045b37aef13 8014383: StringJoiner example in class description not in sync with streams API
psandoz
parents: 17333
diff changeset
    50
 * String desiredString = sj.toString();
4045b37aef13 8014383: StringJoiner example in class description not in sync with streams API
psandoz
parents: 17333
diff changeset
    51
 * }</pre>
4045b37aef13 8014383: StringJoiner example in class description not in sync with streams API
psandoz
parents: 17333
diff changeset
    52
 * <p>
4045b37aef13 8014383: StringJoiner example in class description not in sync with streams API
psandoz
parents: 17333
diff changeset
    53
 * A {@code StringJoiner} may be employed to create formatted output from a
4045b37aef13 8014383: StringJoiner example in class description not in sync with streams API
psandoz
parents: 17333
diff changeset
    54
 * {@link java.util.stream.Stream} using
19214
e5901820c3c1 8015318: Extend Collector with 'finish' operation
briangoetz
parents: 19074
diff changeset
    55
 * {@link java.util.stream.Collectors#joining(CharSequence)}. For example:
17934
4045b37aef13 8014383: StringJoiner example in class description not in sync with streams API
psandoz
parents: 17333
diff changeset
    56
 *
4045b37aef13 8014383: StringJoiner example in class description not in sync with streams API
psandoz
parents: 17333
diff changeset
    57
 * <pre> {@code
4045b37aef13 8014383: StringJoiner example in class description not in sync with streams API
psandoz
parents: 17333
diff changeset
    58
 * List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
4045b37aef13 8014383: StringJoiner example in class description not in sync with streams API
psandoz
parents: 17333
diff changeset
    59
 * String commaSeparatedNumbers = numbers.stream()
4045b37aef13 8014383: StringJoiner example in class description not in sync with streams API
psandoz
parents: 17333
diff changeset
    60
 *     .map(i -> i.toString())
19214
e5901820c3c1 8015318: Extend Collector with 'finish' operation
briangoetz
parents: 19074
diff changeset
    61
 *     .collect(Collectors.joining(", "));
17181
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    62
 * }</pre>
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    63
 *
19214
e5901820c3c1 8015318: Extend Collector with 'finish' operation
briangoetz
parents: 19074
diff changeset
    64
 * @see java.util.stream.Collectors#joining(CharSequence)
e5901820c3c1 8015318: Extend Collector with 'finish' operation
briangoetz
parents: 19074
diff changeset
    65
 * @see java.util.stream.Collectors#joining(CharSequence, CharSequence, CharSequence)
17181
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    66
 * @since  1.8
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    67
*/
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    68
public final class StringJoiner {
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    69
    private final String prefix;
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    70
    private final String delimiter;
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    71
    private final String suffix;
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    72
25967
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
    73
    /** Contains all the string components added so far. */
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
    74
    private String[] elts;
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
    75
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
    76
    /** The number of string components added so far. */
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
    77
    private int size;
17181
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    78
25967
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
    79
    /** Total length in chars so far, excluding prefix and suffix. */
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
    80
    private int len;
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
    81
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
    82
    /**
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
    83
     * When overriden by the user to be non-null via {@link setEmptyValue}, the
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
    84
     * string returned by toString() when no elements have yet been added.
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
    85
     * When null, prefix + suffix is used as the empty value.
17181
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    86
     */
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    87
    private String emptyValue;
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    88
25967
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
    89
    private static final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
    90
17181
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    91
    /**
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    92
     * Constructs a {@code StringJoiner} with no characters in it, with no
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    93
     * {@code prefix} or {@code suffix}, and a copy of the supplied
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    94
     * {@code delimiter}.
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    95
     * If no characters are added to the {@code StringJoiner} and methods
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    96
     * accessing the value of it are invoked, it will not return a
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    97
     * {@code prefix} or {@code suffix} (or properties thereof) in the result,
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    98
     * unless {@code setEmptyValue} has first been called.
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
    99
     *
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   100
     * @param  delimiter the sequence of characters to be used between each
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   101
     *         element added to the {@code StringJoiner} value
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   102
     * @throws NullPointerException if {@code delimiter} is {@code null}
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   103
     */
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   104
    public StringJoiner(CharSequence delimiter) {
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   105
        this(delimiter, "", "");
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   106
    }
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   107
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   108
    /**
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   109
     * Constructs a {@code StringJoiner} with no characters in it using copies
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   110
     * of the supplied {@code prefix}, {@code delimiter} and {@code suffix}.
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   111
     * If no characters are added to the {@code StringJoiner} and methods
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   112
     * accessing the string value of it are invoked, it will return the
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   113
     * {@code prefix + suffix} (or properties thereof) in the result, unless
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   114
     * {@code setEmptyValue} has first been called.
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   115
     *
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   116
     * @param  delimiter the sequence of characters to be used between each
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   117
     *         element added to the {@code StringJoiner}
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   118
     * @param  prefix the sequence of characters to be used at the beginning
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   119
     * @param  suffix the sequence of characters to be used at the end
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   120
     * @throws NullPointerException if {@code prefix}, {@code delimiter}, or
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   121
     *         {@code suffix} is {@code null}
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   122
     */
18778
7214a903b084 8017231: Add StringJoiner.merge
alanb
parents: 17934
diff changeset
   123
    public StringJoiner(CharSequence delimiter,
7214a903b084 8017231: Add StringJoiner.merge
alanb
parents: 17934
diff changeset
   124
                        CharSequence prefix,
7214a903b084 8017231: Add StringJoiner.merge
alanb
parents: 17934
diff changeset
   125
                        CharSequence suffix) {
17181
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   126
        Objects.requireNonNull(prefix, "The prefix must not be null");
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   127
        Objects.requireNonNull(delimiter, "The delimiter must not be null");
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   128
        Objects.requireNonNull(suffix, "The suffix must not be null");
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   129
        // make defensive copies of arguments
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   130
        this.prefix = prefix.toString();
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   131
        this.delimiter = delimiter.toString();
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   132
        this.suffix = suffix.toString();
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   133
    }
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   134
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   135
    /**
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   136
     * Sets the sequence of characters to be used when determining the string
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   137
     * representation of this {@code StringJoiner} and no elements have been
21965
a7e08a4d1e02 8029489: StringJoiner spec for setEmptyValue() and length() is malformatted
smarks
parents: 19214
diff changeset
   138
     * added yet, that is, when it is empty.  A copy of the {@code emptyValue}
17181
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   139
     * parameter is made for this purpose. Note that once an add method has been
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   140
     * called, the {@code StringJoiner} is no longer considered empty, even if
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   141
     * the element(s) added correspond to the empty {@code String}.
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   142
     *
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   143
     * @param  emptyValue the characters to return as the value of an empty
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   144
     *         {@code StringJoiner}
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   145
     * @return this {@code StringJoiner} itself so the calls may be chained
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   146
     * @throws NullPointerException when the {@code emptyValue} parameter is
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   147
     *         {@code null}
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   148
     */
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   149
    public StringJoiner setEmptyValue(CharSequence emptyValue) {
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   150
        this.emptyValue = Objects.requireNonNull(emptyValue,
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   151
            "The empty value must not be null").toString();
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   152
        return this;
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   153
    }
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   154
25967
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   155
    private static int getChars(String s, char[] chars, int start) {
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   156
        int len = s.length();
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   157
        s.getChars(0, len, chars, start);
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   158
        return len;
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   159
    }
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   160
17181
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   161
    /**
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   162
     * Returns the current value, consisting of the {@code prefix}, the values
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   163
     * added so far separated by the {@code delimiter}, and the {@code suffix},
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   164
     * unless no elements have been added in which case, the
25967
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   165
     * {@code prefix + suffix} or the {@code emptyValue} characters are returned.
17181
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   166
     *
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   167
     * @return the string representation of this {@code StringJoiner}
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   168
     */
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   169
    @Override
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   170
    public String toString() {
25967
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   171
        final String[] elts = this.elts;
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   172
        if (elts == null && emptyValue != null) {
17181
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   173
            return emptyValue;
25967
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   174
        }
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   175
        final int size = this.size;
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   176
        final int addLen = prefix.length() + suffix.length();
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   177
        if (addLen == 0) {
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   178
            compactElts();
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   179
            return size == 0 ? "" : elts[0];
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   180
        }
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   181
        final String delimiter = this.delimiter;
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   182
        final char[] chars = new char[len + addLen];
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   183
        int k = getChars(prefix, chars, 0);
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   184
        if (size > 0) {
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   185
            k += getChars(elts[0], chars, k);
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   186
            for (int i = 1; i < size; i++) {
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   187
                k += getChars(delimiter, chars, k);
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   188
                k += getChars(elts[i], chars, k);
17181
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   189
            }
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   190
        }
25967
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   191
        k += getChars(suffix, chars, k);
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   192
        return jla.newStringUnsafe(chars);
17181
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   193
    }
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   194
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   195
    /**
18778
7214a903b084 8017231: Add StringJoiner.merge
alanb
parents: 17934
diff changeset
   196
     * Adds a copy of the given {@code CharSequence} value as the next
17181
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   197
     * element of the {@code StringJoiner} value. If {@code newElement} is
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   198
     * {@code null}, then {@code "null"} is added.
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   199
     *
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   200
     * @param  newElement The element to add
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   201
     * @return a reference to this {@code StringJoiner}
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   202
     */
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   203
    public StringJoiner add(CharSequence newElement) {
25967
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   204
        final String elt = String.valueOf(newElement);
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   205
        if (elts == null) {
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   206
            elts = new String[8];
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   207
        } else {
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   208
            if (size == elts.length)
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   209
                elts = Arrays.copyOf(elts, 2 * size);
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   210
            len += delimiter.length();
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   211
        }
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   212
        len += elt.length();
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   213
        elts[size++] = elt;
17181
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   214
        return this;
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   215
    }
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   216
18778
7214a903b084 8017231: Add StringJoiner.merge
alanb
parents: 17934
diff changeset
   217
    /**
7214a903b084 8017231: Add StringJoiner.merge
alanb
parents: 17934
diff changeset
   218
     * Adds the contents of the given {@code StringJoiner} without prefix and
7214a903b084 8017231: Add StringJoiner.merge
alanb
parents: 17934
diff changeset
   219
     * suffix as the next element if it is non-empty. If the given {@code
7214a903b084 8017231: Add StringJoiner.merge
alanb
parents: 17934
diff changeset
   220
     * StringJoiner} is empty, the call has no effect.
7214a903b084 8017231: Add StringJoiner.merge
alanb
parents: 17934
diff changeset
   221
     *
7214a903b084 8017231: Add StringJoiner.merge
alanb
parents: 17934
diff changeset
   222
     * <p>A {@code StringJoiner} is empty if {@link #add(CharSequence) add()}
7214a903b084 8017231: Add StringJoiner.merge
alanb
parents: 17934
diff changeset
   223
     * has never been called, and if {@code merge()} has never been called
7214a903b084 8017231: Add StringJoiner.merge
alanb
parents: 17934
diff changeset
   224
     * with a non-empty {@code StringJoiner} argument.
7214a903b084 8017231: Add StringJoiner.merge
alanb
parents: 17934
diff changeset
   225
     *
7214a903b084 8017231: Add StringJoiner.merge
alanb
parents: 17934
diff changeset
   226
     * <p>If the other {@code StringJoiner} is using a different delimiter,
7214a903b084 8017231: Add StringJoiner.merge
alanb
parents: 17934
diff changeset
   227
     * then elements from the other {@code StringJoiner} are concatenated with
7214a903b084 8017231: Add StringJoiner.merge
alanb
parents: 17934
diff changeset
   228
     * that delimiter and the result is appended to this {@code StringJoiner}
7214a903b084 8017231: Add StringJoiner.merge
alanb
parents: 17934
diff changeset
   229
     * as a single element.
7214a903b084 8017231: Add StringJoiner.merge
alanb
parents: 17934
diff changeset
   230
     *
7214a903b084 8017231: Add StringJoiner.merge
alanb
parents: 17934
diff changeset
   231
     * @param other The {@code StringJoiner} whose contents should be merged
7214a903b084 8017231: Add StringJoiner.merge
alanb
parents: 17934
diff changeset
   232
     *              into this one
7214a903b084 8017231: Add StringJoiner.merge
alanb
parents: 17934
diff changeset
   233
     * @throws NullPointerException if the other {@code StringJoiner} is null
19074
84a8d23e8f32 8020539: Clean up doclint problems in java.util package, part 2
bpb
parents: 19071
diff changeset
   234
     * @return This {@code StringJoiner}
18778
7214a903b084 8017231: Add StringJoiner.merge
alanb
parents: 17934
diff changeset
   235
     */
7214a903b084 8017231: Add StringJoiner.merge
alanb
parents: 17934
diff changeset
   236
    public StringJoiner merge(StringJoiner other) {
7214a903b084 8017231: Add StringJoiner.merge
alanb
parents: 17934
diff changeset
   237
        Objects.requireNonNull(other);
25967
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   238
        if (other.elts == null) {
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   239
            return this;
18778
7214a903b084 8017231: Add StringJoiner.merge
alanb
parents: 17934
diff changeset
   240
        }
25967
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   241
        other.compactElts();
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   242
        return add(other.elts[0]);
18778
7214a903b084 8017231: Add StringJoiner.merge
alanb
parents: 17934
diff changeset
   243
    }
7214a903b084 8017231: Add StringJoiner.merge
alanb
parents: 17934
diff changeset
   244
25967
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   245
    private void compactElts() {
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   246
        if (size > 1) {
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   247
            final char[] chars = new char[len];
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   248
            int i = 1, k = getChars(elts[0], chars, 0);
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   249
            do {
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   250
                k += getChars(delimiter, chars, k);
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   251
                k += getChars(elts[i], chars, k);
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   252
                elts[i] = null;
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   253
            } while (++i < size);
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   254
            size = 1;
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   255
            elts[0] = jla.newStringUnsafe(chars);
17181
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   256
        }
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   257
    }
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   258
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   259
    /**
21965
a7e08a4d1e02 8029489: StringJoiner spec for setEmptyValue() and length() is malformatted
smarks
parents: 19214
diff changeset
   260
     * Returns the length of the {@code String} representation
a7e08a4d1e02 8029489: StringJoiner spec for setEmptyValue() and length() is malformatted
smarks
parents: 19214
diff changeset
   261
     * of this {@code StringJoiner}. Note that if
17181
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   262
     * no add methods have been called, then the length of the {@code String}
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   263
     * representation (either {@code prefix + suffix} or {@code emptyValue})
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   264
     * will be returned. The value should be equivalent to
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   265
     * {@code toString().length()}.
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   266
     *
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   267
     * @return the length of the current value of {@code StringJoiner}
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   268
     */
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   269
    public int length() {
25967
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   270
        return (size == 0 && emptyValue != null) ? emptyValue.length() :
0060a996fe1c 8054221: StringJoiner imlementation optimization
igerasim
parents: 21965
diff changeset
   271
            len + prefix.length() + suffix.length();
17181
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   272
    }
e3d13a15c5c0 5015163: (str) String merge/join that is the inverse of String.split()
jgish
parents:
diff changeset
   273
}