Dictionary 使用Java8流API的HashMap的平均计数?
我有一张以下类型的Dictionary 使用Java8流API的HashMap的平均计数?,dictionary,java-8,java-stream,Dictionary,Java 8,Java Stream,我有一张以下类型的地图 public class MapUtils { private Map<String, Integer> queryCounts = new HashMap<>(); public void averageCounters(){ int totalCounts = queryCounts.values().stream().reduce(0, Integer::sum); queryCounts = queryCoun
地图
public class MapUtils {
private Map<String, Integer> queryCounts = new HashMap<>();
public void averageCounters(){
int totalCounts = queryCounts.values().stream().reduce(0, Integer::sum);
queryCounts = queryCounts.entrySet()
.stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
(Map.Entry::getValue)/totalCounts
));
}
如果需要就地修改,最好使用
Map.replaceAll
而不是流API:
int totalCounts = queryCounts.values().stream()
.collect(Collectors.summingInt(Integer::intValue));
queryCounts.replaceAll((k, v) -> v/totalCounts);
然而,在您的情况下,这个解决方案是有问题的,因为除法结果将被四舍五入到一个int
数字,因此您几乎总是在结果中得到零。实际上,代码中也存在同样的问题。您可能希望将Map
作为结果类型。因此,您可能需要创建一个全新的地图:
Map<String, Double> averages = queryCounts.entrySet().stream()
.collect(Collectors.toMap(Entry::getKey,
e -> ((double)e.getValue())/totalCounts));
最后,还有一个选择,它是最有效的,但肮脏。在调用averageCounters()
之后,您的代码假定原始(非平均)queryCounts
是不必要的。因此,您可以将queryCounts
保留为Map
(这比向Map
计数更有效),但随后更改Map
值类型,如下所示:
double totalCounts = queryCounts.values().stream()
.collect(Collectors.summingInt(Integer::intValue));
Map<String, Object> map = (Map<String, Object>)queryCounts;
map.replaceAll((k, v) -> ((Integer)v)/totalCounts);
Map<String, Double> averages = (Map<String, Double>)map;
queryCounts = null;
double totalCounts=queryCounts.values().stream()
.collect(collector.summingit(Integer::intValue));
Map Map=(Map)查询计数;
map.replaceAll((k,v)->((整数)v)/totalCounts;
Map平均值=(Map)Map;
queryCounts=null;
类似的技巧也存在于收集器.groupingBy
实现中的JDK中。如果您想要就地修改,最好使用映射。replaceAll
而不是流API:
int totalCounts = queryCounts.values().stream()
.collect(Collectors.summingInt(Integer::intValue));
queryCounts.replaceAll((k, v) -> v/totalCounts);
然而,在您的情况下,这个解决方案是有问题的,因为除法结果将被四舍五入到一个int
数字,因此您几乎总是在结果中得到零。实际上,代码中也存在同样的问题。您可能希望将Map
作为结果类型。因此,您可能需要创建一个全新的地图:
Map<String, Double> averages = queryCounts.entrySet().stream()
.collect(Collectors.toMap(Entry::getKey,
e -> ((double)e.getValue())/totalCounts));
最后,还有一个选择,它是最有效的,但肮脏。在调用averageCounters()
之后,您的代码假定原始(非平均)queryCounts
是不必要的。因此,您可以将queryCounts
保留为Map
(这比向Map
计数更有效),但随后更改Map
值类型,如下所示:
double totalCounts = queryCounts.values().stream()
.collect(Collectors.summingInt(Integer::intValue));
Map<String, Object> map = (Map<String, Object>)queryCounts;
map.replaceAll((k, v) -> ((Integer)v)/totalCounts);
Map<String, Double> averages = (Map<String, Double>)map;
queryCounts = null;
double totalCounts=queryCounts.values().stream()
.collect(collector.summingit(Integer::intValue));
Map Map=(Map)查询计数;
map.replaceAll((k,v)->((整数)v)/totalCounts;
Map平均值=(Map)Map;
queryCounts=null;
类似的技巧也存在于JDK中的收集器.groupingBy
实现中