Java的Stream.flatMap()的(种类)逆操作是什么?

Har*_*ald 8 java java-stream

Stream.flatMap()操作转换了一个流

a, b, c
Run Code Online (Sandbox Code Playgroud)

进入包含每个输入元素的零个或多个元素的流,例如

a1, a2, c1, c2, c3
Run Code Online (Sandbox Code Playgroud)

是否有相反的操作将一些元素分成一个新元素?

  • 它不是.reduce(),因为它只产生一个结果
  • 它不是collect(),因为它只填充容器(afaiu)
  • 它不是forEach(),因为它只返回void并且与副作用一起使用

它存在吗?我可以用任何方式模拟它吗?

Har*_*ald 7

最后我发现这flatMap就是它自己的“逆”。我发现这flatMap不一定会增加元素的数量。它还可以通过为某些元素发出空流来减少元素的数量。为了实现 group-by 操作,by 调用的函数flatMap需要最小的内部状态,即最新的元素。它要么返回一个空流,要么在组的末尾返回简化为组的代表。

这是一个快速实现,如果传入的两个元素不属于同一组(即它们之间是组边界),则groupBorder必须返回。true假设您的组元素是combiner元组 (int, string),则该组函数会将 (1,a)、(1,a)、(1,a) 组合为 (3,a)。

public class GroupBy<X> implements Function<X, Stream<X>>{

  private final BiPredicate<X, X> groupBorder;
  private final BinaryOperator<X> combiner;
  private X latest = null;

  public GroupBy(BiPredicate <X, X> groupBorder,
                 BinaryOperator<X> combiner) {
    this.groupBorder = groupBorder;
    this.combiner = combiner;
  }

  @Override
  public Stream<X> apply(X elem) {
    // TODO: add test on end marker as additonal parameter for constructor
    if (elem==null) {
      return latest==null ? Stream.empty() : Stream.of(latest);
    }
    if (latest==null) {
      latest = elem;
      return Stream.empty();
    }
    if (groupBorder.test(latest, elem)) {
      Stream<X> result = Stream.of(latest);
      latest = elem;
      return result;
    }
    latest = combiner.apply(latest,  elem);
    return Stream.empty();
  }
}
Run Code Online (Sandbox Code Playgroud)

但有一个警告:要发送整个流的最后一组,必须将结束标记作为最后一个元素粘贴到流中。上面的代码假设它是null,但是可以添加一个额外的结束标记测试器。

我无法想出一个不依赖结束标记的解决方案。

此外,我也没有在传入和传出元素之间进行转换。对于一个独特的操作,这会起作用。对于计数操作,前面的步骤必须将各个元素映射到计数对象。