有没有可能;“合并”;Java8流的元素?

有没有可能;“合并”;Java8流的元素?,java,java-8,java-stream,Java,Java 8,Java Stream,我可以用Java8流分析以前和/或以后的元素吗 例如,我可以数一数相同的相邻数字吗 public class Merge { public static void main(String[] args) { Stream<Integer> stream = Stream.of(0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1); // How to get 3, 2, 2, 4 from above } } 公共类合并{ 公共

我可以用Java8流分析以前和/或以后的元素吗

例如,我可以数一数相同的相邻数字吗

public class Merge {
   public static void main(String[] args) {

      Stream<Integer> stream = Stream.of(0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1);

      // How to get 3, 2, 2, 4 from above

   }
}
公共类合并{
公共静态void main(字符串[]args){
Stream-Stream=Stream.of(0,0,0,1,1,0,0,1,1,1);
//如何从上面得到3,2,2,4
}
}

如果希望它是惰性的,那么必须通过
Stream.iterator()
Stream.spliterator()
来转义流API

否则,方法是使用自定义收集器调用终端操作
Stream.collect(Collector)
,这将消耗整个流



你几乎可以用flatMap来做这件事。它适用于无限流,而对于有限流,我看不到一种从内部检测流结束的方法

    Stream<Integer> stream = Stream.of(0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1);

    Stream<Integer> flatMap = stream.flatMap(new Function<Integer, Stream<Integer>>() {
        Integer prev = null;
        int count;
        public java.util.stream.Stream<Integer> apply(Integer i) {
            if ( i.equals(prev)) {
                count++;
                return Stream.empty();
            } else {
                int c = count;
                count = 1;
                prev = i;
                if ( c > 0 ) {
                    return Stream.of(c);
                } else {
                    return Stream.empty();
                }
            }
        };
    });

    flatMap.forEach(i -> {
        System.out.println(i);
    });
Stream-Stream=Stream.of(0,0,0,1,1,0,0,1,1,1);
Stream flatMap=Stream.flatMap(新函数(){
整数prev=null;
整数计数;
public java.util.stream.stream应用(整数i){
如果(i.equals(prev)){
计数++;
返回Stream.empty();
}否则{
int c=计数;
计数=1;
prev=i;
如果(c>0){
(c)的回流;
}否则{
返回Stream.empty();
}
}
};
});
flatMap.forEach(i->{
系统输出打印LN(i);
});
也就是说,对于这类事情,您可能可以从rxjava中获得更好的里程数(您可以使用Subject根据自己的意愿发出值,并能够检测流的结尾)


当然,如果您想避开流边界,有许多选项,如Christoffers答案所示。

如果您不介意两条语句,您可以设置一个列表来填充计数,然后使用
减少

List<Integer> counts = new ArrayList<>();
Stream.of(0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1).reduce((i, j) -> {
    if (counts.isEmpty()) {
        counts.add(1);
    }

    if (j == i) {
        int index = counts.size() - 1;
        counts.set(index, counts.get(index) + 1);
    } else {
        counts.add(1);
    }
    return j;
});
List counts=new ArrayList();
(0,0,0,1,1,0,0,1,1,1,1,1,1,1)流。减少((i,j)->{
if(counts.isEmpty()){
增加(1);
}
如果(j==i){
int index=counts.size()-1;
counts.set(索引,counts.get(索引)+1);
}否则{
增加(1);
}
返回j;
});

在普通Java中,单通道且没有中间数据结构:没有。提供了您正在寻找的内容。我可以在
StreamEx
中编写自定义聚合对象吗?您可以将StreamEx视为通用
API的扩展。因此,没有限制,您可以编写自己的聚合对象。解决方案必须与并行流一起工作,还是仅使用顺序方法就足够了?几乎没有解决方案,并行计算如何?这取决于实际问题是什么。我想在这里展示的技巧是如何仅在某些情况下使用flatMap和空/单流来发出流元素,这可能并不明显(他最初的查找元素的问题,即使可能,仍然需要类似的东西来更改流中元素的数量)。至于Parallel。。。祝你好运,尤其是无限流。我同意,但是
flatMap
不是这个工作的合适工具。我必须承认这是一个巧妙的技巧,但你不能处理有限的
流。完成此类任务的唯一方法是使用Christoff Hammarström提出的
拆分器。然后可以抑制并行计算并处理
流的结尾。
    Stream<Integer> stream = Stream.of(0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1);

    Stream<Integer> flatMap = stream.flatMap(new Function<Integer, Stream<Integer>>() {
        Integer prev = null;
        int count;
        public java.util.stream.Stream<Integer> apply(Integer i) {
            if ( i.equals(prev)) {
                count++;
                return Stream.empty();
            } else {
                int c = count;
                count = 1;
                prev = i;
                if ( c > 0 ) {
                    return Stream.of(c);
                } else {
                    return Stream.empty();
                }
            }
        };
    });

    flatMap.forEach(i -> {
        System.out.println(i);
    });
List<Integer> counts = new ArrayList<>();
Stream.of(0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1).reduce((i, j) -> {
    if (counts.isEmpty()) {
        counts.add(1);
    }

    if (j == i) {
        int index = counts.size() - 1;
        counts.set(index, counts.get(index) + 1);
    } else {
        counts.add(1);
    }
    return j;
});