1 /* |
1 /* |
2 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. Oracle designates this |
7 * published by the Free Software Foundation. Oracle designates this |
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
22 * or visit www.oracle.com if you need additional information or have any |
22 * or visit www.oracle.com if you need additional information or have any |
23 * questions. |
23 * questions. |
24 */ |
24 */ |
25 package java.util; |
25 package java.util; |
|
26 |
|
27 import sun.misc.JavaLangAccess; |
|
28 import sun.misc.SharedSecrets; |
26 |
29 |
27 /** |
30 /** |
28 * {@code StringJoiner} is used to construct a sequence of characters separated |
31 * {@code StringJoiner} is used to construct a sequence of characters separated |
29 * by a delimiter and optionally starting with a supplied prefix |
32 * by a delimiter and optionally starting with a supplied prefix |
30 * and ending with a supplied suffix. |
33 * and ending with a supplied suffix. |
65 public final class StringJoiner { |
68 public final class StringJoiner { |
66 private final String prefix; |
69 private final String prefix; |
67 private final String delimiter; |
70 private final String delimiter; |
68 private final String suffix; |
71 private final String suffix; |
69 |
72 |
70 /* |
73 /** Contains all the string components added so far. */ |
71 * StringBuilder value -- at any time, the characters constructed from the |
74 private String[] elts; |
72 * prefix, the added element separated by the delimiter, but without the |
75 |
73 * suffix, so that we can more easily add elements without having to jigger |
76 /** The number of string components added so far. */ |
74 * the suffix each time. |
77 private int size; |
75 */ |
78 |
76 private StringBuilder value; |
79 /** Total length in chars so far, excluding prefix and suffix. */ |
77 |
80 private int len; |
78 /* |
81 |
79 * By default, the string consisting of prefix+suffix, returned by |
82 /** |
80 * toString(), or properties of value, when no elements have yet been added, |
83 * When overriden by the user to be non-null via {@link setEmptyValue}, the |
81 * i.e. when it is empty. This may be overridden by the user to be some |
84 * string returned by toString() when no elements have yet been added. |
82 * other value including the empty String. |
85 * When null, prefix + suffix is used as the empty value. |
83 */ |
86 */ |
84 private String emptyValue; |
87 private String emptyValue; |
|
88 |
|
89 private static final JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); |
85 |
90 |
86 /** |
91 /** |
87 * Constructs a {@code StringJoiner} with no characters in it, with no |
92 * Constructs a {@code StringJoiner} with no characters in it, with no |
88 * {@code prefix} or {@code suffix}, and a copy of the supplied |
93 * {@code prefix} or {@code suffix}, and a copy of the supplied |
89 * {@code delimiter}. |
94 * {@code delimiter}. |
123 Objects.requireNonNull(suffix, "The suffix must not be null"); |
128 Objects.requireNonNull(suffix, "The suffix must not be null"); |
124 // make defensive copies of arguments |
129 // make defensive copies of arguments |
125 this.prefix = prefix.toString(); |
130 this.prefix = prefix.toString(); |
126 this.delimiter = delimiter.toString(); |
131 this.delimiter = delimiter.toString(); |
127 this.suffix = suffix.toString(); |
132 this.suffix = suffix.toString(); |
128 this.emptyValue = this.prefix + this.suffix; |
|
129 } |
133 } |
130 |
134 |
131 /** |
135 /** |
132 * Sets the sequence of characters to be used when determining the string |
136 * Sets the sequence of characters to be used when determining the string |
133 * representation of this {@code StringJoiner} and no elements have been |
137 * representation of this {@code StringJoiner} and no elements have been |
146 this.emptyValue = Objects.requireNonNull(emptyValue, |
150 this.emptyValue = Objects.requireNonNull(emptyValue, |
147 "The empty value must not be null").toString(); |
151 "The empty value must not be null").toString(); |
148 return this; |
152 return this; |
149 } |
153 } |
150 |
154 |
|
155 private static int getChars(String s, char[] chars, int start) { |
|
156 int len = s.length(); |
|
157 s.getChars(0, len, chars, start); |
|
158 return len; |
|
159 } |
|
160 |
151 /** |
161 /** |
152 * Returns the current value, consisting of the {@code prefix}, the values |
162 * Returns the current value, consisting of the {@code prefix}, the values |
153 * added so far separated by the {@code delimiter}, and the {@code suffix}, |
163 * added so far separated by the {@code delimiter}, and the {@code suffix}, |
154 * unless no elements have been added in which case, the |
164 * unless no elements have been added in which case, the |
155 * {@code prefix + suffix} or the {@code emptyValue} characters are returned |
165 * {@code prefix + suffix} or the {@code emptyValue} characters are returned. |
156 * |
166 * |
157 * @return the string representation of this {@code StringJoiner} |
167 * @return the string representation of this {@code StringJoiner} |
158 */ |
168 */ |
159 @Override |
169 @Override |
160 public String toString() { |
170 public String toString() { |
161 if (value == null) { |
171 final String[] elts = this.elts; |
|
172 if (elts == null && emptyValue != null) { |
162 return emptyValue; |
173 return emptyValue; |
163 } else { |
174 } |
164 if (suffix.equals("")) { |
175 final int size = this.size; |
165 return value.toString(); |
176 final int addLen = prefix.length() + suffix.length(); |
166 } else { |
177 if (addLen == 0) { |
167 int initialLength = value.length(); |
178 compactElts(); |
168 String result = value.append(suffix).toString(); |
179 return size == 0 ? "" : elts[0]; |
169 // reset value to pre-append initialLength |
180 } |
170 value.setLength(initialLength); |
181 final String delimiter = this.delimiter; |
171 return result; |
182 final char[] chars = new char[len + addLen]; |
|
183 int k = getChars(prefix, chars, 0); |
|
184 if (size > 0) { |
|
185 k += getChars(elts[0], chars, k); |
|
186 for (int i = 1; i < size; i++) { |
|
187 k += getChars(delimiter, chars, k); |
|
188 k += getChars(elts[i], chars, k); |
172 } |
189 } |
173 } |
190 } |
|
191 k += getChars(suffix, chars, k); |
|
192 return jla.newStringUnsafe(chars); |
174 } |
193 } |
175 |
194 |
176 /** |
195 /** |
177 * Adds a copy of the given {@code CharSequence} value as the next |
196 * Adds a copy of the given {@code CharSequence} value as the next |
178 * element of the {@code StringJoiner} value. If {@code newElement} is |
197 * element of the {@code StringJoiner} value. If {@code newElement} is |
180 * |
199 * |
181 * @param newElement The element to add |
200 * @param newElement The element to add |
182 * @return a reference to this {@code StringJoiner} |
201 * @return a reference to this {@code StringJoiner} |
183 */ |
202 */ |
184 public StringJoiner add(CharSequence newElement) { |
203 public StringJoiner add(CharSequence newElement) { |
185 prepareBuilder().append(newElement); |
204 final String elt = String.valueOf(newElement); |
|
205 if (elts == null) { |
|
206 elts = new String[8]; |
|
207 } else { |
|
208 if (size == elts.length) |
|
209 elts = Arrays.copyOf(elts, 2 * size); |
|
210 len += delimiter.length(); |
|
211 } |
|
212 len += elt.length(); |
|
213 elts[size++] = elt; |
186 return this; |
214 return this; |
187 } |
215 } |
188 |
216 |
189 /** |
217 /** |
190 * Adds the contents of the given {@code StringJoiner} without prefix and |
218 * Adds the contents of the given {@code StringJoiner} without prefix and |
205 * @throws NullPointerException if the other {@code StringJoiner} is null |
233 * @throws NullPointerException if the other {@code StringJoiner} is null |
206 * @return This {@code StringJoiner} |
234 * @return This {@code StringJoiner} |
207 */ |
235 */ |
208 public StringJoiner merge(StringJoiner other) { |
236 public StringJoiner merge(StringJoiner other) { |
209 Objects.requireNonNull(other); |
237 Objects.requireNonNull(other); |
210 if (other.value != null) { |
238 if (other.elts == null) { |
211 final int length = other.value.length(); |
239 return this; |
212 // lock the length so that we can seize the data to be appended |
240 } |
213 // before initiate copying to avoid interference, especially when |
241 other.compactElts(); |
214 // merge 'this' |
242 return add(other.elts[0]); |
215 StringBuilder builder = prepareBuilder(); |
243 } |
216 builder.append(other.value, other.prefix.length(), length); |
244 |
217 } |
245 private void compactElts() { |
218 return this; |
246 if (size > 1) { |
219 } |
247 final char[] chars = new char[len]; |
220 |
248 int i = 1, k = getChars(elts[0], chars, 0); |
221 private StringBuilder prepareBuilder() { |
249 do { |
222 if (value != null) { |
250 k += getChars(delimiter, chars, k); |
223 value.append(delimiter); |
251 k += getChars(elts[i], chars, k); |
224 } else { |
252 elts[i] = null; |
225 value = new StringBuilder().append(prefix); |
253 } while (++i < size); |
226 } |
254 size = 1; |
227 return value; |
255 elts[0] = jla.newStringUnsafe(chars); |
|
256 } |
228 } |
257 } |
229 |
258 |
230 /** |
259 /** |
231 * Returns the length of the {@code String} representation |
260 * Returns the length of the {@code String} representation |
232 * of this {@code StringJoiner}. Note that if |
261 * of this {@code StringJoiner}. Note that if |
236 * {@code toString().length()}. |
265 * {@code toString().length()}. |
237 * |
266 * |
238 * @return the length of the current value of {@code StringJoiner} |
267 * @return the length of the current value of {@code StringJoiner} |
239 */ |
268 */ |
240 public int length() { |
269 public int length() { |
241 // Remember that we never actually append the suffix unless we return |
270 return (size == 0 && emptyValue != null) ? emptyValue.length() : |
242 // the full (present) value or some sub-string or length of it, so that |
271 len + prefix.length() + suffix.length(); |
243 // we can add on more if we need to. |
|
244 return (value != null ? value.length() + suffix.length() : |
|
245 emptyValue.length()); |
|
246 } |
272 } |
247 } |
273 } |