You can make your own Collector
, but it will likely not be as efficient.
The following collector is somewhat equivalent to doing filter("foo").limit(10)
.
class FilterFooAndLimit10Collector<T> implements Collector<T, List<T>, Stream<T>> {
@Override
public Supplier<List<T>> supplier() {
return () -> new ArrayList<>();
}
@Override
public BiConsumer<List<T>, T> accumulator() {
return (list, elem) -> {
if (!"foo".equals(elem)) list.add(elem);
};
}
@Override
public BinaryOperator<List<T>> combiner() {
return (list1, list2) -> {
var res = new ArrayList<T>(list1.size() + list2.size());
res.addAll(list1);
res.addAll(list2);
return res;
};
}
@Override
public Function<List<T>, Stream<T>> finisher() {
return list -> list.stream().limit(10);
}
@Override
public Set<Collector.Characteristics> characteristics() {
return new HashSet<>();
}
}
You can use it like this:
Stream
.of("foo", "bar", "baz", "foo", "quux", "corge", "fred", "waldo", "spam", "ham", "eggs", "foo", "foobar", "xyzzy")
.collect(new FilterFooAndLimit10Collector<String>())
.forEach(x -> System.out.println(x));
This will yield the output
bar
baz
quux
corge
fred
waldo
spam
ham
eggs
foobar
You can, of course, modify it to take constructor parameters for a wider range of behavior, or optimize it using some other data structure, but I would personally just prefer commonSequence(stream)
.