Java中如何使用merge方法增加HashMap的值?

问题描述 投票:0回答:3

我有以下列表并使用

LinkedHashMap

我想将key增加

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()
方法,但不知道“
<??????>
”表示的第三个参数应该是什么(参见代码)。

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

java hashmap java-stream
3个回答
3
投票

merge方法的第三个参数是

BiFunction
,即接受两个泛型类型V(值的类型)参数并返回所述值的合并的功能接口。

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

在您的情况下,由于对于每个键,您总是映射值 1 然后递增它,因此您可以通过将两个冲突值

BiFunction
相加,或者通过将 1 添加到先前映射的值来实现
(v1, v2) -> v1 + v2
合并价值
(v1, v2) -> v1 + 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);

1
投票

如果仅需要对整数值进行递增/递减,则更经济的方法(创建更少的

Integer
实例)是使用可变整数类(如
AtomicInteger
)作为值类型。

递增/递减将变得微不足道:

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

0
投票

如果地图中不存在,则它从

0
开始,我添加
+1

为了从

zero
开始计数,您可以使用方法
compute()
,该方法需要一个keyremappingFunction,允许根据key现有值计算新值 :

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}
  • 4
    10
    - 出现两次,因此将与
    1
    的值相关联;
  • 5
    2
    - 只会遇到一次,因此会映射到
    0
    的值(因为第一次遇到的键是必需的,即地图中不存在) )

但是,我想用

merge()

使用

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

然后,当第二次、第三次等遇到这样的键时,remappingFunction将用于组合旧值和新值(

1
),即值将增加一。

为了获得与上面所示的

merge()
相同的结果,我们可以在
merge()
周围放置条件。在条件内部,我们可以使用
putIfAbsent()
来初始化条目 will
0
。如果给定的键不存在,
putIfAbsent()
将返回
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}
© www.soinside.com 2019 - 2024. All rights reserved.