场景

Java8新特性-Stream对集合进行操作的常用API:

​​Java8新特性-Stream对集合进行操作的常用API_霸道流氓气质的博客

如果 Map 中包含元素,用户希望替换元素;如果 Map 中没有元素,用户希望添加元素;

此外,用户还希望执行其他相关操作。

Java 8 为 Map 接口引入了不少新方法,某些方法能为开发提供极大的便利。

注:


实现

1、computerIfAbsent

如果键存在,返回对应的值,否则通过提供的函数计算新的值并保存

V computeIfAbsent(K key, Function<? super K, ? extends V>mappingFunction)

以经典的斐波那契数递归计算为例进行讨论。

//效率极低的算法
int fib(int n){
if (n<2) {
return n;
} else {
return fib(n-1) + fib(n-2);
}
}

代码的问题在于需要进行大量重复的计算,(如 fib(5) =fib(4) + fib(3) = fib(3) + fib(2) + fib(2)+fib(1) = ...),

导致程序效率极低。可以利用缓存解决这个问题,函数式编程将这种技术称为记忆化。

BigInteger fibCache(long i){
if(i == 0) return BigInteger.ZERO;
if(i == 1) return BigInteger.ONE;
return cache.computeIfAbsent(i,n ->fibCache(n-2).add(fibCache(n-1)));
}

computeIfAbsent 方法在缓存中搜索给定的数字,存在则返回对应的值,

否则使用提供的 Function 计算新的值,将其保存在缓存中并返回。

2、computeIfPresent

仅当与某个值关联的键在 Map 中存在时,computeIfPresent才会更新该值

V computeIfPresent(K key,    BiFunction<? super K, ? super V, ? extends V>remappingFunction)

统计一段文本中特定单次的出现次数

public Map<String,Integer> countWords(String passage,String... strings){
Map<String,Integer> wordCounts = new HashMap<>();
//将特定单词置于映射中,并将计数器设置为 0
Arrays.stream(strings).forEach(s->wordCounts.put(s,0));
//读取文本,仅更新特定单词的出现次数
Arrays.stream(passage.split(" ")).forEach(word -> wordCounts.computeIfPresent(word,(key,value)->value+1));
return wordCounts;
}

方法调用

String passage = "gong zhonghao badao de cheng xv yuan, badao de cheng xv yuan, badao de cheng xv yuan";
Map<String, Integer> stringIntegerMap = countWords(passage, "badao", "de");
System.out.println(stringIntegerMap);//{badao=3, de= 3}

3、replace

将现有键的值替换为新的值 前提是键已经存在。如果键不存在,replace 不会执行任何操作

Map<String,Integer> map = new HashMap<>();
map.put("a",1);
System.out.println(map);//{a=1}
map.replace("b",2);
System.out.println(map);//{a=1}
map.replace("a",3);
System.out.println(map);//{a= 3}

4、getOrDefault

如果键在 Map 中存在,返回对应的值,否则返回默认值 但不会将这个键添加到映射中。

System.out.println(map);//{a=3}
System.out.println(map.getOrDefault("c",0));//0
System.out.println(map);//{a= 3}

5、merge

如果键在 Map 中不存在,返回提供的值,否则计算新的值

System.out.println(map);//{a=3}
//a存在,对a的值进行累加
map.merge("a",1,(old,new_)->old+new_);
System.out.println(map);//{a=4}
//b不存在,返回默认值1,并put
map.merge("b",1,(old,new_)->old+new_);
System.out.println(map);//{a=4, b=1}
//b已经存在,按照function 此时为乘法
map.merge("b",2,(old,new_)->old*new_);
System.out.println(map);//{a=4, b= 2}

给定一段文本,统计所有单次的出现次数

public Map<String,Integer> fullWordCounts(String passage){
Map<String,Integer> wordCounts = new HashMap<>();
//将逗号替换成空格
String testString = passage.toLowerCase().replaceAll("\\W"," ");
//split("\\s+") \\s表示空格 +表示一个或多个
Arrays.stream(testString.split("\\s+")).forEach(word ->wordCounts.merge(word,1,Integer::sum));
return wordCounts;
}

首先将逗号替换成空格,然后按照一个或者多个空格进行spilit。

方法调用:

String passage1 = "gong zhonghao badao de cheng xv yuan, badao de cheng xv yuan, badao de cheng xv yuan";
Map<String, Integer> stringIntegerMap1 = fullWordCounts(passage1);
System.out.println(stringIntegerMap1);//{yuan=3, de=3, badao=3, gong=1, zhonghao=1, cheng=3, xv=3}

 6、Compute

根据现有的键和值计算新的值

System.out.println(map);//{a=4, b=2}
map.compute("a",(key,value)->value + 2);
System.out.println(map);//{a=6, b=2}

7、putIfAbsent

如果键在 Map 中不存在,将其关联到给定的值

System.out.println(map);//{a=6, b=2}
map.putIfAbsent("b",3);
map.putIfAbsent("c",8);
System.out.println(map);//{a=6, b=2, c=8}

8、replaceAll

将 Map 中每个条目的值替换为对当前条目调用给定函数后的结果

System.out.println(map);//{a=6, b=2, c=8}
map.replaceAll((key,value)-> value +1);
System.out.println(map);//{a=7, b=3, c=9}