【发布时间】:2017-10-17 08:35:42
【问题描述】:
我正在玩一点 Java 流,我想出了一个解决问题的方法,我想与你分享,看看我的方法是否正确。
我从https://catalog.data.gov/dataset/consumer-complaint-database 下载了一个数据集,其中包含超过 70 万条客户投诉记录。 我使用的信息如下:
公司名称 产品名称
我的目标是获得以下结果:
数据集中出现次数较多的 10 家公司
数据集中出现次数较多的 10 个产品
得到类似的东西
Map<String, Map<String,Integer>>
其中,主地图的key为公司名称,二级地图的key为产品名称,其值为产品在该公司被投诉的次数。
所以我所做的解决方案如下:
@Test
public void joinGroupingsTest() throws URISyntaxException, IOException {
String path = CsvReaderTest.class.getResource("/complains.csv").toURI().toString();
complains = CsvReader.readFileStreamComplain(path.substring(path.indexOf('/')+1));
Map<String, List<Complain>> byCompany = complains.parallelStream()
.collect(Collectors.groupingBy(Complain::getCompany))
.entrySet().stream()
.sorted((f1, f2) -> Long.compare(f2.getValue().size(), f1.getValue().size()))
.limit(10)
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
Map<String, List<Complain>> byProduct = complains.parallelStream()
.collect(Collectors.groupingBy(Complain::getProduct))
.entrySet().stream()
.sorted((f1, f2) -> Long.compare(f2.getValue().size(), f1.getValue().size()))
.limit(10)
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
Map<String, List<Complain>> map = complains.parallelStream()
.filter((x) -> byCompany.get(x.getCompany()) != null
&& byProduct.get(x.getProduct()) != null)
.collect(Collectors.groupingBy(Complain::getCompany));
Map<String, Map<String, Long>> map2 = map.entrySet().parallelStream()
.collect(Collectors.toMap(
e -> e.getKey(),
e -> e.getValue().stream()
.collect(Collectors.groupingBy(Complain::getProduct, Collectors.counting()))
));
System.out.println(map2);
}
如您所见,我有几个步骤可以实现这一目标:
1) 我得到了 10 家发生次数较多的公司以及相关的投诉(记录)
2) 我得到了 10 种出现次数较多的产品以及相关的投诉(记录)
3) 我得到一张以公司名称为关键字的地图,该地图在之前计算的前 10 名公司中以及同样在前 10 名产品中的产品的抱怨
4) 我进行所需的转换以获得我想要的地图。
除了在两个不同的线程中分叉和分离步骤 1 和 2 之外,是否还有其他考虑因素需要我提高性能甚至以更好的方式使用流。
谢谢!
【问题讨论】:
-
如果数据集中投诉较多的 10 种产品没有被投诉较多的 10 家公司中的任何一家销售怎么办?我认为这是您设计解决方案时的错误。此外,您正在遍历整个数据集 3 次,这看起来不是很理想,恕我直言
-
使用流进行聚合并没有什么坏处,但是,使用
parallelStream可能会产生开销。我经常在我的 API 中使用stream。这是一个相关的线程:stackoverflow.com/questions/20375176/… -
没有理由分开最后两个流操作,只需将最后一个的
groupingBy收集器作为第二个参数传递给前一个的groupingBy收集器。 -
@Holger 你是对的,这肯定是一个修复,我不知道我能做到这一点
标签: java performance java-8 java-stream collectors