[英]To use streams to find keys in a list with max occurance
我们有一个列表:
List<String> strList = Arrays.asList("10.0 string1", "10.3 string2", "10.0 string3", "10.4 string4","10.3 string5");
每个条目都是一个由 2 个由空格分隔的字符串组成的字符串。 目标是找到所有出现次数最多的条目(即出现 2 次的 10.0 和 10.3)。
以下代码有效。 问题是这 3 个陈述可以减少到 1 个或至少 2 个吗?
var map2 = strList.stream()
.map(m -> {String[] parts = m.split(" "); return parts[0];})
.collect((Collectors.groupingBy(Function.identity(),LinkedHashMap::new, Collectors.counting())));
var max3 = map2.entrySet().stream()
.max((entry1, entry2) -> entry1.getValue() > entry2.getValue() ? 1 : -1)
.get()
.getValue();
var listOfMax2 = map2.entrySet().stream()
.filter(entry -> entry.getValue() == max3)
.map(Map.Entry::getKey)
.collect(Collectors.toList());
System.out.println(listOfMax2);
如果您将变量的名称更改为有意义的名称,那么您拥有的代码非常简单。 您可以编写一个自定义收集器,但我怀疑它是否值得付出努力,并且能够使您的代码更具可读性。 我能想到的最简单的解决方案是,如果你坚持链接你的 ZF7B44CFFAFD5C52223D5498196C8A2E7BZ,首先建立频率然后反转 map 以使用值(频率)作为键和键作为值并收集到树形图,这是排序的按键,并获取最后一个条目:
List<String> strList = Arrays.asList("10.0 string1", "10.3 string2", "10.0 string3", "10.4 string4", "10.3 string5");
var mostFrequentEntries =
strList.stream()
.map(s -> s.substring(0, s.indexOf(' ')))
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet()
.stream()
.collect(Collectors.groupingBy(Map.Entry::getValue, TreeMap::new, Collectors.mapping(Map.Entry::getKey, Collectors.toList())))
.lastEntry().getValue();
System.out.println(mostFrequentEntries);
strList
.stream()
.map(s -> s.substring(0, s.indexOf(" ")))
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet()
.stream()
.collect(Collectors.groupingBy(Entry::getValue))
.entrySet()
.stream()
.max(Entry.comparingByKey())
.ifPresentOrElse(longListEntry -> longListEntry.getValue().stream().map(Entry::getKey).forEach(System.out::println),
() -> System.out.println("No Value Found"));
印刷:
10.3
10.0
非常坦率的:
Stream#map
获取密钥。Collectors#groupingBy
将密钥的频率作为Map
获取。Stream#max
频率并在O(n)
时间内打印List
。我知道的这种最简单的方法是从目标值的频率计数开始,并在数据结构中返回最大值和 map 以供后续处理。
这是一些数据(添加到您的演示中)
List<String> strList = Arrays.asList("10.0 string1",
"10.0 string2", "10.3 string3", "10.0 string4",
"10.3 string5", "10.4 string 6", "10.3 string7",
"10.4 string8", "10.5 string 9", "10.6 string10");
首先,stream 列表并根据频率创建 map。 这是通过使用toMap
并增加重复键的计数来完成的。
然后 stream 该 map 的条目寻找最大计数。 然后在SimpleEntry
数据结构中返回计数和 map。
Entry<Integer,Map<String,Integer>> result = strList.stream()
.map(str -> str.split("\\s+")[0]).
collect(Collectors.collectingAndThen(
Collectors.toMap(s -> s, s -> 1,Integer::sum),
m -> new SimpleEntry<>(m.entrySet()
.stream()
.map(Entry::getValue)
.max(Integer::compare).orElse(0),m)));
int max = result.getKey();
result.getValue().forEach((k,v)-> {
if (v == max) {
System.out.println(k);
}
});
印刷
10.4
10.3
10.0
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.