简体   繁体   English

在 Java 8 中是否有更简洁的方法来执行此操作 - 地图操作

[英]Is there a more concise way to do this in Java 8 - Map manipulation

A very common operation on maps of collections is to create a new collection with an initial value when the key is not present, or if the key is present, do some function on the existing collection.集合映射上的一个非常常见的操作是在键不存在时创建具有初始值的新集合,或者如果键存在,则对现有集合执行一些功能。 Take for example a Map<String, Set<Integer>> , if the key is not there, create a Set with an initial value of 1. If the key is there, add the value map.size()+1 to the set (or replace this function with some other simple one-liner operation).Map<String, Set<Integer>>为例,如果键不存在,则创建一个初始值为 1 的 Set。如果键存在,则将值 map.size()+1 添加到集合中(或将此功能替换为其他一些简单的单行操作)。 In Java 7, it's straightforward with if/else, but pretty verbose.在 Java 7 中,使用 if/else 很简单,但非常冗长。 I can only come up with the below code for Java 8, which isn't much better (actually worse due to more lines of code).我只能为 Java 8 提供以下代码,这并没有好多少(实际上由于代码行更多而更糟)。 Is there a way to make this more concise?有没有办法让它更简洁?

public void process(Map<String, Set<Integer>> m, String key) {
    m.compute(key, (k, v) -> {
        if (v == null) {
            v = new HashSet<>();
            v.add(1);
            return v;
        } else {
            v.add(v.size() + 1);
            return v;
        }
    });
}

Here's another alternative:这是另一种选择:

Set<Integer> set = m.computeIfAbsent (key , k -> new HashSet<> ());
set.add(set.size() + 1);

The only reason this is a two liner (instead of one) is the need to obtain the current size of the Set in order to decide which value to add to it.这是一个两行(而不是一个)的唯一原因是需要获取Set的当前大小,以便决定向其中添加哪个值。

Not a one-liner unfortunately but it does its magic and is also directly more readable (downside : it creates a new HashSet<>() everytime)不幸的是,它不是单行的,但它确实具有魔力,并且直接更具可读性(缺点:它每次都会创建一个新的HashSet<>()

m.putIfAbsent(key, new HashSet<>());
// Solution 1 :
m.compute(key, (k, v) -> {v.add(v.size() + 1); return v;});
// Solution 2 :
Set<Integer> s = m.get(key);
s.add(s.size() + 1);

Or as proposed by @Thilo and inspired by @Eran或由@Thilo 提出并受@Eran 启发

m.computeIfAbsent(key, k -> new HashSet<>()).add(m.get(key).size() + 1);

The one liner is possible because it returns the value it computed as mentioned in the javadoc一个衬里是可能的,因为它返回它计算的值,如javadoc中所述

If the specified key is not already associated with a value (or is mapped to null), attempts to compute its value using the given mapping function and enters it into this map unless null.如果指定的键尚未与值关联(或映射为 null),则尝试使用给定的映射函数计算其值并将其输入到此映射中,除非为 null。

There is even a similar example in the javadoc javadoc中甚至还有一个类似的例子

map.computeIfAbsent(key, k -> new HashSet()).add(v); map.computeIfAbsent(key, k -> new HashSet()).add(v);

The little trade-off of the liner is the extra call to m.get(key) which is not happening with the solution of @Eran班轮的小权衡是对m.get(key)的额外调用,@Eran 的解决方案没有发生这种情况

Set<Integer> v = m.getOrDefault(key, new HashSet<>());
v.add(v.size() + 1);
m.put(key, v);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM