当前位置: 首页 > 知识库问答 >
问题:

重构if-else块以使用Map.ComputeIfAstant Map.ComputeIfPresent错误结果

颜修为
2023-03-14

我有课

public class Gezana {
    private String name;
    private long value;
}

和列表,如:

List<Gezana> list = List.of(new Gezana("foo", 2), 
                            new Gezana("foo", 2),
                            new Gezana("foo", 2),
                            new Gezana("foo", 2), 
                            new Gezana("bar", 5),
                            new Gezana("bar", 5), 
                            new Gezana("bar", 5), 
                            new Gezana("doo", 9), 
                            new Gezana("doo", 9),
                            new Gezana("kee", 12));

我需要创建一个地图使用上面的列表名称作为键和值的总和作为值。我以前是这样做的:

Map<String, Long> oldMap = new HashMap<>(); 
for (Gezana gez : list) {            
    if (oldMap.containsKey(gez.getName())) {
        oldMap.put(gez.getName(), oldMap.get(gez.getName()) + gez.getValue());
    } else{
        oldMap.put(gez.getName(), gez.getValue());
    }          
}        
System.out.println("old map:" + oldMap);

我需要重构上面的内容,并考虑使用Map.ComputeIfAstent&Map.ComputeIfPresent,但没有得到预期的结果

Map<String, Long> map = new HashMap<>(); 
for (Gezana gez : list) {            
    map.computeIfAbsent(gez.getName(), k -> gez.getValue());     
    map.computeIfPresent(gez.getName(), (k, v)->  v + gez.getValue());              
}
System.out.println("new map:" + map);

输出:

old map:{bar=15, doo=18, foo=8, kee=12}
new map:{bar=20, doo=27, foo=10, kee=24}

看起来新的映射对于每添加一个键都有一个附加值,但是我看不出使用ComputeIfAstent&computeIfPresent方法有什么错误。有什么提示吗?

共有2个答案

夏侯星洲
2023-03-14

最好应用map::merge函数:

 Map<String, Long> oldMap = new HashMap<>();
for (Gezana gez : list) {
    oldMap.merge(gez.getName(), gez.getValue(), Long::sum);
}

System.out.println("old map:" + oldMap);

或者使用流APICollectors.GroupingByCollectors.SummingLong:

Map<String, Long> newMap = list.stream()
        .collect(Collectors.groupingBy(
            Gezana::getName, 
            Collectors.summingLong(Gezana::getValue)
        ));
System.out.println("new map:" + newMap);

输出:

old map:{bar=15, doo=18, foo=8, kee=12}
new map:{bar=15, doo=18, foo=8, kee=12}
胡玉书
2023-03-14

问题是computeif缺席总是添加到映射中;然后,computeifpresent将更新computeif缺席可能刚刚添加的内容。

因此,当第一次遇到一个名称时,它的值会被添加两次--一次由ComputeIfAstent添加,然后由ComputeIfPresent添加。

您可以使用ComputeIfAstent/ComputeIfPresent执行此操作,如下所示:

map.computeIfAbsent(gez.getName(), k -> 0L);     
map.computeIfPresent(gez.getName(), (k, v)->  v + gez.getValue());

compute:

map.compute(gez.getName(), (k, v) -> (v != null ? v : 0L) + get.getValue());

但合并会更容易:

oldMap.merge(gez.getName(), gez.getValue(), Long::sum);

或者,直接从列表中:

Map<String, Long> map = 
    list.stream().collect(groupingBy(Gezana::getName, summingLong(Gezana::getValue)))
 类似资料:
  • if 是用于测试某个条件(布尔型或逻辑型)的语句,如果该条件成立,则会执行 if 后由大括号括起来的代码块,否则就忽略该代码块继续执行后续的代码。 if condition { // do something } 如果存在第二个分支,则可以在上面代码的基础上添加 else 关键字以及另一代码块,这个代码块中的代码只有在条件不满足时才会执行。if 和 else 后的两个代码块是相互独立的分

  • if选择结构只在条件为true时采取操作,条件为false时则忽略这个操作。利用if/else选择结构则可以在条件为true时和条件为false时采取不同操作。例如,下列伪代码: if student's grade is greater than or equal to 60   print "Passed" else   print "Failed" 在学生成绩大于或等于60时打印“Pa

  • 我是新来的ReactJS。在我的索引页上,loginState的初始状态 但是我的控制台在设置状态之后,两个modalStatus都打印为false。我做错什么了吗?请引导我。如果有任何帮助,我将不胜感激。

  • 问题内容: 为什么我总是从Postgres收到以下错误? 我阅读了PostgreSQL:文档:8.3:控制结构。首先,我尝试执行一个困难的查询(带有子查询),但是随后我尝试执行一个简单的查询,如下所示: 错误仍然相同。我究竟做错了什么? 问题答案: 您不能在plpgsql函数之外使用PL / pgSQL语句。而且,如果此片段来自plpgsql函数,那么它也是无稽之谈。您不能像T- SQL一样直接返

  • Perl条件语句有助于决策,这需要程序员指定一个或多个要由程序评估或测试的条件,以及在条件被确定为真时要执行的一个或多个语句,以及可选的其他条件如果确定条件为假,则执行语句。 以下是大多数编程语言中的典型决策结构的一般性 - 数字0,字符串'0'和“”,空列表()和undef在布尔上下文中都是false ,所有其他值都为true 。 否定真正的价值! 或not返回特殊的假值。 Perl编程语言提供

  • 本文向大家介绍C# if, if...else, if... else if ,包括了C# if, if...else, if... else if 的使用技巧和注意事项,需要的朋友参考一下 示例 该if语句用于控制程序的流程。一条if语句根据Boolean表达式的值标识要运行的语句。 对于单个语句,braces{}是可选的,但建议使用。 该if还可以有一个else条款,将在案件条件的计算结果来执