groupingBy在Java-8中的操作

时间:2014-10-15 09:36:10

标签: java-8 apache-spark tf-idf text-classification

我正在尝试在Java 8上重写Spark的文本分类(http://chimpler.wordpress.com/2014/06/11/classifiying-documents-using-naive-bayes-on-apache-spark-mllib/)的着名示例。

我有一个问题 - 在这段代码中,我正在为获取所有文件中所有单词的idf做一些数据准备工作:

    termDocsRdd.collect().stream().flatMap(doc -> doc.getTerms().stream()
                                .map(term -> new ImmutableMap.Builder<String, String>()
                                .put(doc.getName(),term)
                                .build())).distinct()        

我坚持使用groupBy操作。 (我需要按术语对此进行分组,因此每个术语必须是一个键,值必须是一系列文档)。 在Scala中,此操作看起来非常简单 - .groupBy(_._ 2)。 但是我怎么能用Java做到这一点?

我试着写一些像:

    .groupingBy(term -> term, mapping((Document) d -> d.getDocNameContainsTerm(term), toList()));

但这是不正确的......

有人知道如何用Java编写它吗?

非常感谢你。

1 个答案:

答案 0 :(得分:2)

如果我理解正确,你想做这样的事情:

import static java.util.stream.Collectors.*;

Map<Term, Set<Document>> collect = termDocsRdd.collect().stream().flatMap(
 doc -> doc.getTerms().stream().map(term -> new AbstractMap.SimpleEntry<>(doc, term)))
.collect(groupingBy(Map.Entry::getValue, mapping(Map.Entry::getKey, toSet())));

Map.Entry / AbstractMap.SimpleEntry的使用是由于Java-8中缺少标准Pair<K,V>类。 Map.Entry实现可以履行此角色,但代价是具有不直观和冗长的类型和方法名称(关于作为Pair实现的任务)。


如果您正在使用当前的Eclipse版本(我使用LunaSR1 20140925进行测试)及其有限的类型推断,那么您必须帮助编译器:

Map<Term, Set<Document>> collect = termDocsRdd.collect().stream().flatMap(
 doc -> doc.getTerms().stream().<Map.Entry<Document,Term>>map(term -> new AbstractMap.SimpleEntry<>(doc, term)))
.collect(groupingBy(Map.Entry::getValue, mapping(Map.Entry::getKey, toSet())));