I have a map of type HashMap<String, List<Integer>>
.
I want to find the maximum value for each map entry, and in turn find the minimum of those maximum values.
I know this can be done using a couple of for loops. But was wondering if there's another way of doing it (maybe with streams?)
The final result I'm looking for is an integer.
Example:
HashMap<String, List<Integer>> values = new HashMap<>();
values.put("a", Arrays.asList(4, 8, 9, 10)); // max value is 10
values.put("b", Arrays.asList(20, 32, 1, 2)); // max value is 32
values.put("c", Arrays.asList(11, 50, 20, 6)); // max value is 50
// I need the min value out of the above maximums i.e. 10 (final answer)
CodePudding user response:
You can use the methods Collections.min and Collections.max
HashMap<String, List<Integer>> myMap = new HashMap<>();
Integer min = Collections.min(myMap.values().stream().map(Collections::max).collect(Collectors.toList()));
CodePudding user response:
I want to find the maximum value for each map entry and inturn find minimum of those maximum values.
Then IntSummaryStatistics
is your new friend. This object is meant to provide such information as min and max values, the number of consumed elements, average and their total.
As a container for the result, we can use a map Map<String, IntSummaryStatistics>
that will hold statistics of every value mapped to this value's key. For that we need a help of collectors flatMapping()
and summarizingInt()
.
Then to get the smallest maximum, we should process the values of this map.
Map<String, List<Integer>> sourceMap =
Map.of("a", List.of(4, 8, 9, 10), // max value is 10
"b", List.of(20, 32, 1, 2), // max value is 32
"c", List.of(11, 50, 20, 6)); // max value is 50
Map<String, IntSummaryStatistics> statisticsByKey = sourceMap.entrySet().stream()
.collect(Collectors.groupingBy(
Map.Entry::getKey,
Collectors.flatMapping(entry -> entry.getValue().stream(), // flatens each list
Collectors.summarizingInt(Integer::intValue)) // creates IntSummaryStatistics object based on the values of each list
));
statisticsByKey.forEach((k, v)
-> System.out.println(k " -> min: " v.getMin() " max: " v.getMax()));
int smallestMaximum = statisticsByKey.values().stream()
.mapToInt(IntSummaryStatistics::getMax)
.min() // produces OptionalInt as a result
.orElse(-1); // returns a default value of `-1` if result is not present
System.out.println("smallestMaximum: " smallestMaximum);
Output:
a -> min: 4 max: 10
b -> min: 1 max: 32
c -> min: 6 max: 50
smallestMaximum: 10
A link to the Online Demo
CodePudding user response:
Given a map
Hash<String, List<Integer>> values;
Find each list's max, then use IntStream
's min()
over those:
Integer minMax = values.values().stream()
.map(Collections::max)
.mapToInt(n -> n).min().getAsInt();
See live demo finding 10
from your sample data.
For the IntStream
only version (probably more efficient), stream the values (ie the lists of integers), then find each list's max by converting each list to an IntStream
and getting its max, then find min of those:
Integer minMax = values.values().stream()
.mapToInt(v -> v.stream().mapToInt(n -> n).max().getAsInt())
.min().getAsInt();
See live demo.
This assumes all lists are not empty and the map itself is not empty.
There is also a way that makes use of Collections.max(), but produces an
Optional` which is slightly more obtuse way IMHO
Integer minMax = values.values().stream()
.map(Collections::max)
.collect(Collectors.minBy(Integer::compareTo)).get();
See live demo.