是否有可能在java 8中执行一个懒惰的groupby,返回一个流?

Jos*_*rdo 5 java lazy-loading java-8 java-stream

我有一些大型的文本文件,我想通过对其行进行分组来处理.

我尝试使用新的流媒体功能,比如

return FileUtils.readLines(...) 
            .parallelStream()
            .map(...)
            .collect(groupingBy(pair -> pair[0]));
Run Code Online (Sandbox Code Playgroud)

问题是,AFAIK,这会生成一个Map.

是否有任何方法可以像上面那样生成高级代码,例如,条目流?

更新:我正在寻找的是像python的itertools.groupby.我的文件已经排序(通过pair [0]),我只想逐个加载组.

我已经有了一个迭代解决方案.我只是想知道是否有更多的声明方式来做到这一点.顺便说一句,使用番石榴或其他第三方图书馆不会是一个大问题.

Hol*_*ger 6

您想要实现的任务与分组所做的任务完全不同。不依赖于\xe2\x80\x99s 元素groupingBy的顺序,而是依赖于应用于分类器\xe2\x80\x99s 结果的 \xe2\x80\x99s 算法。StreamMapFunction

\n\n

您想要的是将具有共同属性值的相邻项目折叠成一个List项目。Stream只要您可以保证具有相同属性值的所有项目都聚集在一起,甚至没有必要按该属性进行排序。

\n\n

也许可以将这个任务表述为简化,但对我来说,结果结构看起来太复杂了。

\n\n

因此,除非将对此功能的直接支持添加到 s 中Stream,否则基于迭代器的方法对我来说看起来最实用:

\n\n
class Folding<T,G> implements Spliterator<Map.Entry<G,List<T>>> {\n    static <T,G> Stream<Map.Entry<G,List<T>>> foldBy(\n            Stream<? extends T> s, Function<? super T, ? extends G> f) {\n        return StreamSupport.stream(new Folding<>(s.spliterator(), f), false);\n    }\n    private final Spliterator<? extends T> source;\n    private final Function<? super T, ? extends G> pf;\n    private final Consumer<T> c=this::addItem;\n    private List<T> pending, result;\n    private G pendingGroup, resultGroup;\n\n    Folding(Spliterator<? extends T> s, Function<? super T, ? extends G> f) {\n        source=s;\n        pf=f;\n    }\n    private void addItem(T item) {\n        G group=pf.apply(item);\n        if(pending==null) pending=new ArrayList<>();\n        else if(!pending.isEmpty()) {\n            if(!Objects.equals(group, pendingGroup)) {\n                if(pending.size()==1)\n                    result=Collections.singletonList(pending.remove(0));\n                else {\n                    result=pending;\n                    pending=new ArrayList<>();\n                }\n                resultGroup=pendingGroup;\n            }\n        }\n        pendingGroup=group;\n        pending.add(item);\n    }\n    public boolean tryAdvance(Consumer<? super Map.Entry<G, List<T>>> action) {\n        while(source.tryAdvance(c)) {\n            if(result!=null) {\n                action.accept(entry(resultGroup, result));\n                result=null;\n                return true;\n            }\n        }\n        if(pending!=null) {\n            action.accept(entry(pendingGroup, pending));\n            pending=null;\n            return true;\n        }\n        return false;\n    }\n    private Map.Entry<G,List<T>> entry(G g, List<T> l) {\n        return new AbstractMap.SimpleImmutableEntry<>(g, l);\n    }\n    public int characteristics() { return 0; }\n    public long estimateSize() { return Long.MAX_VALUE; }\n    public Spliterator<Map.Entry<G, List<T>>> trySplit() { return null; }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

Stream通过将其应用于无限流可以最好地证明所得到的折叠的惰性本质:

\n\n
Folding.foldBy(Stream.iterate(0, i->i+1), i->i>>4)\n       .filter(e -> e.getKey()>5)\n       .findFirst().ifPresent(e -> System.out.println(e.getValue()));\n
Run Code Online (Sandbox Code Playgroud)\n