Java的Stream.flatMap()的(种类)逆操作是什么? [英] What is the (kind of) inverse operation to Java's Stream.flatMap()?

查看:108
本文介绍了Java的Stream.flatMap()的(种类)逆操作是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Stream.flatMap()操作转换

a, b, c

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

into a stream that contains zero or more elements for each input element, e.g.

a1, a2, c1, c2, c3

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

Is there the opposite operations that batches up a few elements into one new one?


  • 它不是.reduce(),因为它只产生一个结果

  • 它不是collect(),因为它只填充容器(afaiu)

  • 它不是forEach(),因为它只返回 void 并使用副作用

  • It is not .reduce(), because this produces only one result
  • It is not collect(), because this only fills a container (afaiu)
  • It is not forEach(), because this has returns just void and works with side effects

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

Does it exist? can I simulate it in any way?

推荐答案

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

Finally I figured out that flatMap is its own "inverse" so to say. I oversaw that flatMap not necessarily increases the number of elements. It may also decrease the number of elements by emitting an empty stream for some of the elements. To implement a group-by operation, the function called by flatMap needs minimal internal state, namely the most recent element. It either returns an empty stream or, at the end of a group, it returns the reduced-to group representative.

这是一个快速实现 groupBorder 必须返回 true 如果传入的两个元素不属于同一组,即它们之间是组边界。 组合器是组合函数,例如(1,a),(1,a),(1,a)组合成(3,a),给定你的组元素是,元组(int,string)。

Here is a quick implementation where groupBorder must return true if the two elements passed in do not belong to the same group, i.e. between them is the group border. The combiner is the group function that combines, for example (1,a), (1,a), (1,a) into (3,a), given that your group elements are, tuples (int, string).

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

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

There is one caveat though: to ship the last group of the whole stream, an end marker must be stuck as the last element into the stream. The above code assumes it is null, but an additional end-marker-tester could be added.

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

I could not come up with a solution that does not rely on the end marker.

我还做了不会在传入和传出元素之间进行转换。对于一个独特的操作,这将是有效的。对于计数操作,上一步必须将各个元素映射到计数对象。

Further I did not also convert between incoming and outgoing elements. For a unique-operation, this would just work. For a count-operation, a previous step would have to map individual elements to a counting object.

这篇关于Java的Stream.flatMap()的(种类)逆操作是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆