8017231: Add StringJoiner.merge

Co-authored-by: Henry Jen <henry.jen@oracle.com>
Reviewed-by: psandoz, alanb
This commit is contained in:
Brian Goetz 2013-07-04 20:00:20 +01:00 committed by Alan Bateman
parent fac53ff2dc
commit fd97f9873a
3 changed files with 163 additions and 20 deletions

View File

@ -114,8 +114,9 @@ public final class StringJoiner {
* @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 @@ public final class StringJoiner {
}
/**
* 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 @@ public final class StringJoiner {
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);

View File

@ -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}");
}
}

View File

@ -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 @@ public class StringJoinerTest {
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 @@ public class StringJoinerTest {
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 @@ public class StringJoinerTest {
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 @@ public class StringJoinerTest {
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;