在java流之间共享/重用公共操作序列的最佳方法

oalqel3c  于 2021-07-11  发布在  Java
关注(0)|答案(1)|浏览(272)

如果我在两个流中有一个共同的操作序列,如何共享它们以避免代码重复?到目前为止,我发现我可以使用:

Stream<U> commonSequence(Stream<T> upstream) {
    return upstream.op1().op2().op3()
}

然后把它当作

commonSequence(upStream()).downStream()

但是事情并不是按照发生的顺序写的。我是否忽略了一些技巧,可以让我写一些东西,比如:

upStream().wrap(commonPart).downStream()
mpbci0fu

mpbci0fu1#

你可以自己做 Collector ,但它的效率可能不会那么高。
下面的收集器在某种程度上相当于 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<>();
  }
}

你可以这样使用它:

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

这将产生输出

bar
baz
quux
corge
fred
waldo
spam
ham
eggs
foobar

当然,您可以对它进行修改,以获取更广泛行为的构造函数参数,或者使用其他数据结构对其进行优化,但我个人更喜欢这样 commonSequence(stream) .

相关问题