Last active
July 24, 2019 13:35
-
-
Save michalmela/208b3d3c253ff0ff1a013753a1064846 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.EnumSet; | |
import java.util.Set; | |
import java.util.concurrent.atomic.AtomicInteger; | |
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 java.util.stream.IntStream; | |
import java.util.stream.Stream; | |
import static java.util.Collections.unmodifiableSet; | |
class Scratch { | |
public static void main(String[] args) { | |
System.out.println( | |
Stream.of("foo").collect(new JoiningWithCutoffCollector<>(2, "_")) | |
); | |
System.out.println( | |
Stream.of("foo", "bar").collect(new JoiningWithCutoffCollector<>(2, "_")) | |
); | |
System.out.println( | |
Stream.of("foo", "bar", "baz").collect(new JoiningWithCutoffCollector<>(2, "_")) | |
); | |
System.out.println( | |
Stream.of("foo", "bar", "baz", "boo").collect(new JoiningWithCutoffCollector<>(2, "_")) | |
); | |
} | |
} | |
class JoiningWithCutoffCollector<A> implements Collector<A, JoiningWithCutoffCollector.Intermediate, String> { | |
private final int cutoff; | |
private final String separator; | |
private static final String moreSuffix = "-more"; | |
public static class Intermediate { | |
private final StringBuilder builder; | |
private final AtomicInteger count; | |
public Intermediate() { | |
builder = new StringBuilder(); | |
count = new AtomicInteger(0); | |
} | |
public Intermediate(StringBuilder builder, AtomicInteger count) { | |
this.builder = builder; | |
this.count = count; | |
} | |
} | |
public JoiningWithCutoffCollector(int cutoff, String separator) { | |
this.cutoff = cutoff; | |
this.separator = separator; | |
} | |
@Override | |
public Supplier<Intermediate> supplier() { | |
return Intermediate::new; | |
} | |
@Override | |
public BiConsumer<Intermediate, A> accumulator() { | |
return (intermediate, next) -> { | |
if (intermediate.count.getAndIncrement() < cutoff) { | |
intermediate.builder.append(intermediate.builder.length() > 0 ? separator : "").append(next); | |
} | |
}; | |
} | |
@Override | |
public BinaryOperator<Intermediate> combiner() { | |
return (first, second) -> new Intermediate( | |
new StringBuilder(String.join(separator, first.builder.toString(), second.builder.toString())), | |
new AtomicInteger(first.count.get() + second.count.get()) | |
); | |
} | |
@Override | |
public Function<Intermediate, String> finisher() { | |
return intermediate -> { | |
int finalCount = intermediate.count.get() - cutoff; | |
if (finalCount > 0) { | |
intermediate.builder.append(separator).append(finalCount).append(moreSuffix); | |
} | |
return intermediate.builder.toString(); | |
}; | |
} | |
@Override | |
public Set<Characteristics> characteristics() { | |
return emptySet(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment