diff --git a/guava-tests/test/com/google/common/base/JoinerTest.java b/guava-tests/test/com/google/common/base/JoinerTest.java index d9ed3472184c..8365c093b22d 100644 --- a/guava-tests/test/com/google/common/base/JoinerTest.java +++ b/guava-tests/test/com/google/common/base/JoinerTest.java @@ -26,11 +26,10 @@ import com.google.common.collect.Maps; import com.google.common.testing.NullPointerTester; import java.io.IOException; -import java.util.Arrays; -import java.util.Iterator; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; -import java.util.Set; +import java.util.stream.Collectors; + import junit.framework.AssertionFailedError; import junit.framework.TestCase; @@ -307,6 +306,13 @@ public void test_skipNulls_onMap() { } } + public void testCollector() { + Joiner onChar = Joiner.on(' '); + List input = Lists.newArrayList("This","works","as","a","stream","collector"); + String result = input.stream().collect(onChar); + assertEquals("This works as a stream collector",result); + } + private static class DontStringMeBro implements CharSequence { @Override public int length() { diff --git a/guava/src/com/google/common/base/Joiner.java b/guava/src/com/google/common/base/Joiner.java index 922c1ebde172..46bd795dcfcb 100644 --- a/guava/src/com/google/common/base/Joiner.java +++ b/guava/src/com/google/common/base/Joiner.java @@ -19,12 +19,16 @@ import com.google.common.annotations.Beta; import com.google.common.annotations.GwtCompatible; import com.google.errorprone.annotations.CanIgnoreReturnValue; + import java.io.IOException; -import java.util.AbstractList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; +import java.util.function.BiConsumer; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.stream.Collector; + import org.checkerframework.checker.nullness.qual.Nullable; /** @@ -63,13 +67,17 @@ * @since 2.0 */ @GwtCompatible -public class Joiner { - /** Returns a joiner which automatically places {@code separator} between consecutive elements. */ +public class Joiner implements Collector, String> { + /** + * Returns a joiner which automatically places {@code separator} between consecutive elements. + */ public static Joiner on(String separator) { return new Joiner(separator); } - /** Returns a joiner which automatically places {@code separator} between consecutive elements. */ + /** + * Returns a joiner which automatically places {@code separator} between consecutive elements. + */ public static Joiner on(char separator) { return new Joiner(String.valueOf(separator)); } @@ -121,7 +129,9 @@ public final A appendTo(A appendable, Object[] parts) thr return appendTo(appendable, Arrays.asList(parts)); } - /** Appends to {@code appendable} the string representation of each of the remaining arguments. */ + /** + * Appends to {@code appendable} the string representation of each of the remaining arguments. + */ @CanIgnoreReturnValue public final A appendTo( A appendable, @Nullable Object first, @Nullable Object second, Object... rest) @@ -475,4 +485,32 @@ public Object get(int index) { } }; } + + @Override + public Supplier> supplier() { + return ArrayList::new; + } + + @Override + public BiConsumer, Object> accumulator() { + return List::add; + } + + @Override + public BinaryOperator> combiner() { + return (l1, l2) -> { + l1.addAll(l2); + return l1; + }; + } + + @Override + public Function, String> finisher() { + return this::join; + } + + @Override + public Set characteristics() { + return new HashSet<>(); + } }