如何在 Java 中使用合并方法增加 HashMap 值?

How to increase HashMap value using merge method in Java?

我有以下 list 并使用 LinkedHashMap.

我想将 keyvalue 增加 1(如果键是 地图中不存在 ,它从 0 开始,我添加 +1):

int nums[] = new int[]{4, 10, 5, 4, 2, 10};

Map<Integer, Integer> map = new LinkedHashMap<>();

for (int i = 0; i < nums.length; i++) {
    int key = nums[i];
    int value = map.getOrDefault(key, 0) + 1;

    // I want to use merge method, but have no idea 
    // what should be the 3 rd parameter denoted by "<??????>"
    int value = map.merge(key, 1, <??????>)

    map.put(key, value);
}

但是,我想使用merge()方法,但不知道“<??????>”表示的第三个参数应该是什么(见代码).

那么,在这种情况下如何使用合并方法?

if the key is not present in the map, it starts from 0 and I add +1

为了从 zero 开始计数,您可以使用方法 compute(),它需要一个 keyremappingFunction 允许根据 keyexisting value:[=37 计算 new value =]

int nums[] = new int[]{4, 10, 5, 4, 2, 10};
    
Map<Integer, Integer> map = new LinkedHashMap<>();
    
for (int num : nums) {
    map.compute(num, (k, v) -> v == null ? 0 : v + 1);
}
    
System.out.println(map);

输出:

{4=1, 10=1, 5=0, 2=0}
  • 410 - 出现两次,因此将与 1;
  • 的值相关联
  • 52 - 只会遇到一次,因此会映射到 0 的值(因为第一次遇到的键需要它时间,即不存在在地图中)

However, I want to use merge()

对于 map.merge(num, 1, Integer::sum);,映射中不存在的键将从一开始就与 1 的值相关联。 IE。作为第三个参数提供的 remappingFunction 将不会被执行,并且由提供的 keyvalue[=65 组成的新条目=] 将被放入地图中。

然后当第二次、第三次等遇到此类键时,remappingFunction 将用于组合旧值和新值 (1 ),即值将增加一。

要使用 merge() 获得与上面所示相同的结果,我们可以在 merge() 周围放置条件。在条件中,我们可以使用 putIfAbsent() 来初始化入口 will 0。如果给定的键不存在,putIfAbsent() 将 return null,否则现有值:

int nums[] = new int[]{4, 10, 5, 4, 2, 10};
    
Map<Integer, Integer> map = new LinkedHashMap<>();
    
for (int num : nums) {
    if (map.putIfAbsent(num, 0) != null) {
        map.merge(num, 1, Integer::sum);
    }
}

输出:

{4=1, 10=1, 5=0, 2=0}

merge 方法的第三个参数是 BiFunction,即接受两个泛型 V 参数(您的值的类型)并返回所述值的合并的功能接口。

假设您在您的代码中尝试获取每个键的频率,尽管您写的是“它从 0 开始,我添加 +1”,这里是您尝试的示例。

合并操作由您决定,在您的情况下,它仅包括保留第一个值(已经存在于您的地图中的值),将其递增 1 并忽略第二个值。合并也可以简单地包括将第一个值和第二个值相加,因为对于每个键,您只是映射值 1.

int nums[] = new int[]{4, 10, 5, 4, 2, 10};

Map<Integer, Integer> map = new LinkedHashMap<>();
for (int i = 0; i < nums.length; i++) {
    map.merge(nums[i], 1, (v1, v2) -> v1 + 1);

    //Alternatively summing the two values
    //map.merge(nums[i], 1, (v1, v2) -> v1 + v2);
}

System.out.println(map);

但是,如果您的目标是获取键冲突的次数而不是它们的频率,那么只需将值 1 替换为 0,上面的代码仍然有效。

int nums[] = new int[]{4, 10, 5, 4, 2, 10};

Map<Integer, Integer> map = new LinkedHashMap<>();
for (int i = 0; i < nums.length; i++) {
    map.merge(nums[i], 0, (v1, v2) -> v1 + 1);
}

System.out.println(map);

如果整数值只需要 increment/decrement,更经济的方法(创建的 Integer 的实例较少)将使用可变整数 class(如 AtomicInteger) 作为值类型。

Increment/Decrement 将是微不足道的:

Map<String, AtomicInteger> map = new HashMap<>();
// Create a mapping for key "foo" if not exists, then increment
int n = map.computeIfAbsent("foo", (k) -> new AtomicInteger())
    .incrementAndGet(); // or addAndGet() or similar