8017231: Add StringJoiner.merge
Reviewed-by: psandoz, alanb
Contributed-by: brian.goetz@oracle.com, henry.jen@oracle.com
--- a/jdk/src/share/classes/java/util/StringJoiner.java Thu Jul 04 14:38:44 2013 +0100
+++ b/jdk/src/share/classes/java/util/StringJoiner.java Thu Jul 04 20:00:20 2013 +0100
@@ -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 given {@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,36 @@
return this;
}
+ /**
+ * Adds the contents of the given {@code StringJoiner} without prefix and
+ * suffix as the next element if it is non-empty. If the given {@code
+ * StringJoiner} is empty, the call has no effect.
+ *
+ * <p>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.
+ *
+ * <p>If the other {@code StringJoiner} is using a different delimiter,
+ * then 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 otherBuilder = other.value;
+ if (other.prefix.length() < otherBuilder.length()) {
+ builder.append(otherBuilder, other.prefix.length(), otherBuilder.length());
+ }
+ }
+ return this;
+ }
+
private StringBuilder prepareBuilder() {
if (value != null) {
value.append(delimiter);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/StringJoiner/MergeTest.java Thu Jul 04 20:00:20 2013 +0100
@@ -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
--- a/jdk/test/java/util/StringJoiner/StringJoinerTest.java Thu Jul 04 14:38:44 2013 +0100
+++ b/jdk/test/java/util/StringJoiner/StringJoinerTest.java Thu Jul 04 20:00:20 2013 +0100
@@ -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<String> nextOne = new ArrayList<>();
nextOne.add(TWO);
nextOne.add(THREE);
- nextOne.stream().forEach(sj::add);
+ nextOne.stream().forEachOrdered(sj::add);
String expected = "{"+ONE+DASH+TWO+DASH+THREE+"}";
assertEquals(sj.toString(), expected);
@@ -64,7 +64,7 @@
ArrayList<String> firstOne = new ArrayList<>();
firstOne.add(ONE);
firstOne.add(TWO);
- firstOne.stream().forEach(sj::add);
+ firstOne.stream().forEachOrdered(sj::add);
sj.add(THREE);
@@ -79,29 +79,17 @@
firstOne.add(ONE);
firstOne.add(TWO);
firstOne.add(THREE);
- firstOne.stream().forEach(sj::add);
+ firstOne.stream().forEachOrdered(sj::add);
ArrayList<String> nextOne = new ArrayList<>();
nextOne.add(FOUR);
nextOne.add(FIVE);
- nextOne.stream().forEach(sj::add);
+ nextOne.stream().forEachOrdered(sj::add);
String expected = "{"+ONE+DASH+TWO+DASH+THREE+DASH+FOUR+DASH+FIVE+"}";
assertEquals(sj.toString(), expected);
}
- public void testInto() {
- ArrayList<String> list = new ArrayList<>();
- list.add(ONE);
- list.add(TWO);
- list.add(THREE);
-
- StringJoiner target = new StringJoiner(",", "{", "}");
- assertEquals(target.toString(), "{" + ONE + "," + TWO + "," + THREE +
- "}");
- }
- */
-
public void addCharSequence() {
StringJoiner sj = new StringJoiner(",");
CharSequence cs_one = ONE;