# HG changeset patch # User henryjen # Date 1372837397 25200 # Node ID 368c722db196645dccfe0527a86b9a8b174ef976 # Parent dfb37cc30a678b31b16c80d3123e8ccf849bbb03 8017231: Add StringJoiner.merge Reviewed-by: Contributed-by: brian.goetz@oracle.com, henry.jen@oracle.com diff --git a/src/share/classes/java/util/StringJoiner.java b/src/share/classes/java/util/StringJoiner.java --- a/src/share/classes/java/util/StringJoiner.java +++ b/src/share/classes/java/util/StringJoiner.java @@ -114,8 +114,9 @@ * @throws NullPointerException if {@code prefix}, {@code delimiter}, or * {@code suffix} is {@code null} */ - public StringJoiner(CharSequence delimiter, CharSequence prefix, - CharSequence suffix) { + public StringJoiner(CharSequence delimiter, + CharSequence prefix, + CharSequence suffix) { Objects.requireNonNull(prefix, "The prefix must not be null"); Objects.requireNonNull(delimiter, "The delimiter must not be null"); Objects.requireNonNull(suffix, "The suffix must not be null"); @@ -172,7 +173,7 @@ } /** - * Add the a copy of the supplied {@code CharSequence} value as the next + * Adds a copy of the supplied {@code CharSequence} value as the next * element of the {@code StringJoiner} value. If {@code newElement} is * {@code null}, then {@code "null"} is added. * @@ -184,6 +185,35 @@ return this; } + /** + * Adds the contents of the supplied {@code StringJoiner} without prefix + * and suffix as the next element if it is nonempty. If the supplied + * {@code StringJoiner} is empty, the call has no effect. + * + *
A {@code StringJoiner} is empty if {@link add(CharSequence) add()} + * has never been called, and if {@code merge()} has never been called + * with a non- empty {@code StringJoiner} argument. + * + *
If the other {@code StringJoiner} is using a different delimiter,
+ * elements from the other {@code StringJoiner} are concatenated with that
+ * delimiter and the result is appended to this {@code StringJoiner} as a
+ * single element.
+ *
+ * @param other The {@code StringJoiner} whose contents should be merged
+ * into this one
+ * @throws NullPointerException if the other {@code StringJoiner} is null
+ */
+ public StringJoiner merge(StringJoiner other) {
+ Objects.requireNonNull(other);
+ if (other.value != null) {
+ StringBuilder builder = prepareBuilder();
+ StringBuilder otherBuffer = other.value;
+ for (int i=other.prefix.length(); i < otherBuffer.length(); i++)
+ builder.append(otherBuffer.charAt(i));
+ }
+ return this;
+ }
+
private StringBuilder prepareBuilder() {
if (value != null) {
value.append(delimiter);
diff --git a/test/java/util/StringJoiner/MergeTest.java b/test/java/util/StringJoiner/MergeTest.java
new file mode 100644
--- /dev/null
+++ b/test/java/util/StringJoiner/MergeTest.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8017231
+ * @summary test StringJoiner::merge
+ * @run testng MergeTest
+ */
+
+import java.util.StringJoiner;
+import java.util.stream.Stream;
+import org.testng.annotations.Test;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
+
+@Test
+public class MergeTest {
+ public void testNull() {
+ StringJoiner sj = new StringJoiner(",", "{", "}");
+ try {
+ sj.merge(null);
+ fail("Should throw NullPointerException!");
+ } catch (NullPointerException npe) {
+ // expected
+ }
+ }
+
+ public void testSimple() {
+ StringJoiner sj = new StringJoiner(",", "{", "}");
+ StringJoiner other = new StringJoiner(",", "[", "]");
+ Stream.of("a", "b", "c").forEachOrdered(sj::add);
+ Stream.of("d", "e", "f").forEachOrdered(other::add);
+
+ sj.merge(other);
+ assertEquals(sj.toString(), "{a,b,c,d,e,f}");
+ }
+
+ public void testEmptyOther() {
+ StringJoiner sj = new StringJoiner(",", "{", "}");
+ StringJoiner other = new StringJoiner(",", "[", "]");
+ Stream.of("a", "b", "c").forEachOrdered(sj::add);
+
+ sj.merge(other);
+ assertEquals(sj.toString(), "{a,b,c}");
+
+ other.setEmptyValue("EMPTY");
+ sj.merge(other);
+ assertEquals(sj.toString(), "{a,b,c}");
+ }
+
+ public void testEmptyThis() {
+ StringJoiner sj = new StringJoiner(",", "{", "}");
+ StringJoiner other = new StringJoiner(":", "[", "]");
+ Stream.of("d", "e", "f").forEachOrdered(other::add);
+
+ sj.merge(other);
+ assertEquals(sj.toString(), "{d:e:f}");
+
+ sj = new StringJoiner(",", "{", "}").setEmptyValue("EMPTY");
+ assertEquals(sj.toString(), "EMPTY");
+ sj.merge(other);
+ assertEquals(sj.toString(), "{d:e:f}");
+ }
+
+ public void testEmptyBoth() {
+ StringJoiner sj = new StringJoiner(",", "{", "}");
+ StringJoiner other = new StringJoiner(":", "[", "]");
+
+ sj.merge(other);
+ assertEquals(sj.toString(), "{}");
+
+ other.setEmptyValue("NOTHING");
+ sj.merge(other);
+ assertEquals(sj.toString(), "{}");
+
+ sj = new StringJoiner(",", "{", "}").setEmptyValue("EMPTY");
+ assertEquals(sj.toString(), "EMPTY");
+ sj.merge(other);
+ assertEquals(sj.toString(), "EMPTY");
+ }
+
+ public void testCascadeEmpty() {
+ StringJoiner sj = new StringJoiner(",", "{", "}");
+ StringJoiner o1 = new StringJoiner(":", "[", "]").setEmptyValue("Empty1");
+ StringJoiner o2 = new StringJoiner(",", "<", ">").setEmptyValue("Empty2");
+
+ o1.merge(o2);
+ assertEquals(o1.toString(), "Empty1");
+
+ sj.merge(o1);
+ assertEquals(sj.toString(), "{}");
+ }
+
+ public void testDelimiter() {
+ StringJoiner sj = new StringJoiner(",", "{", "}");
+ StringJoiner other = new StringJoiner(":", "[", "]");
+ Stream.of("a", "b", "c").forEachOrdered(sj::add);
+ Stream.of("d", "e", "f").forEachOrdered(other::add);
+
+ sj.merge(other);
+ assertEquals(sj.toString(), "{a,b,c,d:e:f}");
+ }
+}
\ No newline at end of file
diff --git a/test/java/util/StringJoiner/StringJoinerTest.java b/test/java/util/StringJoiner/StringJoinerTest.java
--- a/test/java/util/StringJoiner/StringJoinerTest.java
+++ b/test/java/util/StringJoiner/StringJoinerTest.java
@@ -27,6 +27,7 @@
* @run testng StringJoinerTest
* @author Jim Gish
*/
+import java.util.ArrayList;
import java.util.StringJoiner;
import org.testng.annotations.Test;
import static org.testng.Assert.assertEquals;
@@ -44,7 +45,6 @@
private static final String FIVE = "Five";
private static final String DASH = "-";
- /* Uncomment when we have streams
public void addAddAll() {
StringJoiner sj = new StringJoiner(DASH, "{", "}");
sj.add(ONE);
@@ -52,7 +52,7 @@
ArrayList