Java 从HashMap获取每个数字的最大出现次数<;整数,列表<;整数>&燃气轮机;
我一直在做一个练习,在这个练习中,我必须找到以下问题的解决方案:我有一个Java 从HashMap获取每个数字的最大出现次数<;整数,列表<;整数>&燃气轮机;,java,java-8,java-stream,Java,Java 8,Java Stream,我一直在做一个练习,在这个练习中,我必须找到以下问题的解决方案:我有一个 HashMap<Integer, List<Integer>> 在本例中,我应该以某种方式获得一个包含以下元素的列表:[2,2,2,8,30,30],因为每个数字的最大出现次数为: 对于2,它是3(在值7中) 如果为8,则为1(值为8) 如果为30,则为2(值为25) 我正在尝试使用streams来实现这一点,我已经编写了以下代码: map.entrySet() .st
HashMap<Integer, List<Integer>>
在本例中,我应该以某种方式获得一个包含以下元素的列表:[2,2,2,8,30,30],因为每个数字的最大出现次数为:
- 对于2,它是3(在值7中)
- 如果为8,则为1(值为8)
- 如果为30,则为2(值为25)
map.entrySet()
.stream()
.map(Map.Entry::getValue)
.collect(Collectors.toList());
这会得到单独的列表,但我需要的是得到一个列表,其中包含任何列表中的所有元素,并且有最多的被提及次数。元素的顺序根本不重要
如果你需要澄清,请问我
提前感谢您的帮助。您可以这样做:
static List<Integer> maxOccurrence(Map<Integer, List<Integer>> input) {
return input.values().stream()
.flatMap(list -> list.stream().collect(Collectors.groupingBy(Function.identity(), Collectors.counting())).entrySet().stream())
.collect(Collectors.groupingBy(Map.Entry::getKey, Collectors.mapping(Map.Entry::getValue, Collectors.maxBy(Comparator.naturalOrder()))))
.entrySet().stream().sorted(Map.Entry.comparingByKey())
.flatMap(e -> LongStream.range(0, e.getValue().get()).mapToObj(x -> e.getKey()))
.collect(Collectors.toList());
}
输出
[2,2,2,8,30,30]
解释
input.values().stream()
[8,30]
[2, 2, 2]
[30, 30, 2]
.flatMap(list -> list.stream().collect(Collectors.groupingBy(Function.identity(), Collectors.counting())).entrySet().stream())
8=1
30=1
2=3
30=2
2=1
.collect(Collectors.groupingBy(Map.Entry::getKey, Collectors.mapping(Map.Entry::getValue, Collectors.maxBy(Comparator.naturalOrder()))))
.flatMap(e -> LongStream.range(0, e.getValue().get()).mapToObj(x -> e.getKey()))
{8=1,2=3,30=2}
2=3
8=1
30=2
.collect(Collectors.groupingBy(Map.Entry::getKey, Collectors.mapping(Map.Entry::getValue, Collectors.maxBy(Comparator.naturalOrder()))))
.flatMap(e -> LongStream.range(0, e.getValue().get()).mapToObj(x -> e.getKey()))
2
2.
2.
8.
30
30
.collect(Collectors.toList())
[2,2,2,8,30,30]
以下是使用streams的快速解决方案:
public static void main(String[] args) {
Map<Integer, List<Integer>> map = new HashMap<>();
map.put(25, Arrays.asList(30, 30, 2));
map.put(7, Arrays.asList(2, 2, 2));
map.put(8, Arrays.asList(8, 30));
List<Integer> result = map.values().stream() // Stream<List<Integer>>
.map(e -> e.stream().collect(Collectors.groupingBy(p -> p, Collectors.counting()))) // Stream<Map<Integer,Long>>
.flatMap(m -> m.entrySet().stream()) // Stream<Entry<Integer,Long>>
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, Long::max)) // Map<Integer,Long>
.entrySet().stream() // Stream<Entry<Integer,Long>>
.flatMap(e -> repeatElement(e.getKey(), e.getValue())) // Stream<Integer>
.collect(Collectors.toList());
System.out.println(result);
}
private static Stream<Integer> repeatElement(Integer key, Long value) {
return Stream.generate(() -> key)
.limit(value);
}
您只需使用以下功能:
List<Integer> result = map.values().stream()
.flatMap(list -> list.stream().collect(Collectors.groupingBy(i -> i, Collectors.summingInt(i -> 1))).entrySet().stream())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, Integer::max)).entrySet().stream()
.flatMap(e -> Collections.nCopies(e.getValue(), e.getKey()).stream())
.collect(Collectors.toList());
我怀疑这件事不可能一蹴而就。你必须使用流吗?似乎循环会使任务更容易。不,这不是必须的;我只是想实践流,不知何故我觉得它必须使用它们来解决;只要使用。我想你可以使用带有自定义收集器的流,只要你练习如何使用它们。你可以使用更简单的
.collector.toMap,而不是.collector(collector.groupby(Map.Entry::getKey,collector.mapping)(Map.Entry::getValue,collector.maxBy(Comparator.naturalOrder()))
(Map.Entry::getKey,Map.Entry::getValue,Long::max))
,这也消除了以后调用get()
(在可选
)的需要。当您使用.collect(Collectors.toMap(Map.Entry::getKey,Map.Entry::getValue,Long::max,TreeMap::new))
时,您不需要后续的(Map.Entry.comparingByKey())
step.@Holger True。既然其他两个答案都是这样的,我就不做了。当然,我也可以使用groupingBy
的版本,它需要一个地图供应商,就像toMap
有这样一个超负荷,但是最后的排序很容易,也很快,而其他两个答案并没有做到这一点,所以我想调整键更好,以突出显示需要排序。
[2, 2, 2, 8, 30, 30]
List<Integer> result = map.values().stream()
.flatMap(list -> list.stream().collect(Collectors.groupingBy(i -> i, Collectors.summingInt(i -> 1))).entrySet().stream())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, Integer::max)).entrySet().stream()
.flatMap(e -> Collections.nCopies(e.getValue(), e.getKey()).stream())
.collect(Collectors.toList());
[2, 2, 2, 8, 30, 30]