# 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 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 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 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 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;