映射条目的原子更新
ConcurrentHashMap只有部分原子更新。
JavaAPI提供了一些新方法,例如:compute方法可以提供一个键和一个计算新值的函数。
map.compute(word,(k,v)->v == null ? 1 : v+1)
注释:ConcurrentHashMap中不允许有null值。很多方法都使用null来指示映射中某个给定的键不存在。
使用并发散列映射来统计一个目录树的Java文件中的所有单词
package concurrentHashMap;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Scanner;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class CHMDemo {
public static ConcurrentHashMap<String,Long> map = new ConcurrentHashMap<>();
public static void process(Path file) {
try(var in = new Scanner(file)){
while(in.hasNext()) {
String word = in.next();
map.merge(word, 1L, Long::sum);
}
}catch (Exception e) {
e.printStackTrace();
}
}
public static Set<Path> descendants(Path rootDir) throws IOException{
try(Stream<Path> entries = Files.walk(rootDir)){
return entries.collect(Collectors.toSet());
}
}
public static void main(String[] args) throws InterruptedException, IOException {
int processors = Runtime.getRuntime().availableProcessors();
ExecutorService executor = Executors.newFixedThreadPool(processors);
Path pathToRoot = Path.of("C:\\Program Files\\Java\\jdk1.8.0_131\\src");
for (Path p : descendants(pathToRoot)) {
if(p.getFileName().toString().endsWith(".java")) {
executor.execute(()->process(p));
}
}
executor.shutdown();
executor.awaitTermination(10, TimeUnit.MINUTES);
map.forEach((k,v)->{
if(v>=10)
System.out.println(k+" occurs "+v+" times");
});
}
}