【问题标题】:Counter with lambda over map java8在映射 java8 上使用 lambda 计数器
【发布时间】:2016-04-17 12:09:21
【问题描述】:

我正在尝试转换:

Map<String,Long> parties = new HashMap<>();
parties.add("a", 1);
...
Long counter = 0l;

for (Long votes : parties.values()){
    counter += votes;
}

对于 Java8 中的 lambda,我使用 reduce 尝试如下:

parties.entrySet().stream().reduce((stringLongEntry, stringLongEntry2) -> /*Here I Stack*/)

但我不知道如何继续。

PS:我知道我可以做到: parties.values().stream().count(); 但我想找到另一种方法。

【问题讨论】:

  • 为什么要另辟蹊径?
  • 您是否总是在值中存储 1?在这种情况下,地图的大小就是您所需要的。
  • @FedericoPeraltaSchaffner 不,我不会放弃 1 ,这只是一个例子
  • 那么为什么你认为parties.values().stream().count()sum包含的值的解决方案?
  • parties.add??

标签: java lambda java-8 hashmap java-stream


【解决方案1】:

如果您始终将1 存储为每个键的值,那么总计数将始终与映射的大小相匹配。您可以通过parties.size() 轻松获取。

如果您为每个键存储不同的值,那么计算地图中有多少值是错误的。您应该将它们相加:

long total = parties.values().stream().mapToLong(v -> v).sum();

【讨论】:

  • 您好,这里的1只是一个例子,可以是任意Long数。关于您的回答,您的解决方案与我的完全一样。这里有 count 的文档:返回此流中元素的计数。这是 reduction 的一个特例,相当于:
    {@code return mapToLong(e -> 1L).sum(); }
  • @RobertoFernandez 这和你的不一样。数到 n 与求和 1 n 次相同,这就是文档所说的。但是如果你在 map 中的值不是 1,那么 count() 和 sum() 会返回不同的值
【解决方案2】:

试试下面的表达式:

counter = parties.values().stream().map((votes) -> votes).reduce(counter, (a, i) -> a+i);

此外,您的代码中几乎没有错误:

  • 使用Map&lt;String,Long&gt; parties = new HashMap&lt;&gt;(); 是正确的方法,但您的方法不会出错。
  • HashMap 没有.add(..) 方法,但是.put(..) 方法:

    parties.put("a",1L);
    
  • 由于您的值为Long,因此您必须使用1L1l 而不是整个1 来指定Long 值。

【讨论】:

  • 我更喜欢写L而不是l,因为最后一个看起来像1
  • 如果您这样做,则不需要map(它只不过是在您的代码中添加字符)...但是,我更喜欢在操作原始值时使用 LongStream .
  • counter 传递给reduce 是没有意义的。求和的唯一有效值是0L,因此您应该直接提供该值而不是现有变量。
【解决方案3】:
  1. parties.values().stream().mapToLong(l -&gt; l).sum();
  2. parties.values().stream().reduce(0L, (a, b) -&gt; a + b);

  1. parties.entrySet().stream().mapToLong(Map.Entry::getValue).sum();
  2. parties.entrySet().stream().mapToLong(Map.Entry::getValue).reduce(0L, (a, b) -&gt; a + b);

cmets 中问题的解释。在这里我们可以写(Map.Entry&lt;String, Long&gt; i) -&gt; i.getValue()i -&gt; i.getValue()。但是,如果我们将其替换为 method reference(如 Map.Entry::getValue),它会更具可读性。

【讨论】:

  • 感谢您的回答,我是 lambdas 新手,'::' 是什么意思?
  • @RobertoFernandez,我在答案中添加了小解释
  • 使用.entrySet().stream().mapToLong(Map.Entry::getValue) 而不是直截了当的.values().stream() 有什么意义?
  • @Holger,OP 通缉entrySet
  • 问题的焦点似乎不是entrySet()(否则,仅映射到之后的值的解决方案只是伪装,而不是适当的答案)。似乎 OP 想要一个基于缩减的解决方案,而不是调用像 count() 这样的现有方法(无论如何都不起作用)......
【解决方案4】:

如果你坚持 entrySet -

parties.entrySet().stream().map(e -> e.getValue()).reduce(0L, (longValue1, longValue2) -> longValue1 + longValue2)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-09-04
    • 2018-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多