我正在尝试在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编写它吗?
非常感谢你。
答案 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())));