【问题标题】:Java, grouping, sorting and collecting maps using streamsJava,使用流对地图进行分组、排序和收集
【发布时间】:2020-03-11 20:48:45
【问题描述】:

我有两张商店地图,我想计算第一张地图中每个品牌的商店数量,但品牌只能在第二张地图中找到。然后我想按每个品牌的商店数量降序对结果进行排序。我的代码如下所示:

Store store, store1, store2, store3, store4, store5, store6;
store = new Store("1", null);
store1 = new Store("2", null);
store2 = new Store("3", null);
Map<String, Store> dynamicShops = new HashMap<>();
dynamicShops.put(store.getId(), store);
dynamicShops.put(store1.getId(), store1);
dynamicShops.put(store2.getId(), store2);

store3 = new Store("1", "ABC");
store4 = new Store("2", "ABC");
store5 = new Store("3", "Abra Cadabra");
store6 = new Store("4", "Abra Cadabra");
Map<String, Store> staticShops = new HashMap<>();
staticShops.put(store3.getId(), store3);
staticShops.put(store4.getId(), store4);
staticShops.put(store5.getId(), store5);
staticShops.put(store6.getId(), store6);

Map<String, Long> stats = dynamicShops.values().stream()
            .collect(groupingBy(s -> staticShops.get(s.getId()).getBrand(), counting()));

Map<String, Long> statsSorted = stats.entrySet().stream()
            .sorted(Map.Entry.<String, Long>comparingByValue().reversed())
            .collect(toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));

statsSorted.entrySet().stream().forEach(s -> System.out.println(s.getKey() + " " + s.getValue()));

并产生我期待的输出:

ABC 2
Abra Cadabra 1

现在我想知道有没有办法在一个流中完成它?

【问题讨论】:

  • 你的意思是Map&lt;String, Long&gt; statsSorted = dynamicShops.values().stream() .collect(groupingBy(s -&gt; staticShops.get(s.getId()).getBrand(), counting())) .entrySet().stream() .sorted(Map.Entry.&lt;String, Long&gt;comparingByValue().reversed()) .collect(toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -&gt; e1, LinkedHashMap::new));
  • @YCF_L,这在技术上是两个流。 ;)
  • 看看stackoverflow.com/questions/109383 并在此处指定使用单流来实现什么目标?
  • @Naman 好吧,我假设只流式传输这些值一次而不是两次,这样会很有效。
  • 效率不取决于您执行了多少流操作。效率取决于 CPU 必须执行的实际操作。您无法按未知的计数进行排序。原则上,您可以实现一个在计数发生变化时即时重新排序的数据结构,但性能会比在排序前计数更差

标签: java java-8 java-stream linkedhashmap


【解决方案1】:

这是一种解决方案:

dynamicShops.values()
            .stream()
            .map(s -> staticShops.get(s.getId()).getBrand())
            .collect(Collectors.collectingAndThen(Collectors.groupingBy(Function.identity(), Collectors.counting()), m -> m.entrySet().stream()))
            .sorted(Entry.<String, Long>comparingByValue().reversed())
            .forEach(s -> System.out.println(s.getKey() + " " + s.getValue()));

【讨论】:

  • 我猜它仍然是两个流。我想知道有没有办法在第一次收集中使用一些 collectAndThen 或类似的东西来做到这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多