How to force max to return ALL maximum values in a Java Stream?
I would group by value and store the values into a TreeMap
in order to have my values sorted, then I would get the max value by getting the last entry as next:
Stream.of(1, 3, 5, 3, 2, 3, 5)
.collect(groupingBy(Function.identity(), TreeMap::new, toList()))
.lastEntry()
.getValue()
.forEach(System.out::println);
Output:
5
5
How to get all objects having the same max value with Java streams?
You could collect to a TreeMap
first and only get the last entry (where the max is)
players.stream()
.collect(Collectors.groupingBy(
Player::getPoints,
TreeMap::new,
Collectors.toList()
))
.lastEntry()
.getValue();
How to get all elements with the highest value with Java streams?
You can do this using a TreeMap
and the Collectors.groupingBy()
:
TreeMap<Integer, List<MyPojo>> map = pojos.stream()
.collect(Collectors.groupingBy(
MyPojo::getPriority,
TreeMap::new,
Collectors.toList()
));
List<MyPojo> maxPrios = map.lastEntry().getValue();
The lastEntry()
will return the pojos with the highest priority, due to the natural ordering of Integer
s where the smallest value will be first, and the largest value will be last.
Collect objects with max value in a list with streams
I did something like this. I group by the score and then find the score with maximum key value. It will return an Optional
of Map.Entry
. It contains both the maximum value and the players that have it. Then I can get the list of players using getValue()
method.
List<Player> value = playerList.stream()
.collect(groupingBy(Player::getScore))
.entrySet()
.stream()
.max(Comparator.comparing(Map.Entry::getKey))
.get()
.getValue();
How can I filter stream by some max value from it?
If you have to do in one pass, you can write a custom Collector to reduce the stream into a list of max elements. Here's an implementation based on this answer by Stuart Marks.
List<MyObject> maxList = list.stream()
.collect(maxList(Comparator.comparing(MyObject::getSome)));
static <T> Collector<T,?,List<T>> maxList(Comparator<? super T> comp) {
return Collector.of(
ArrayList::new,
(list, t) -> {
int c;
if (list.isEmpty() || (c = comp.compare(t, list.get(0))) == 0) {
list.add(t);
} else if (c > 0) {
list.clear();
list.add(t);
}
},
(list1, list2) -> {
if (list1.isEmpty()) {
return list2;
}
if (list2.isEmpty()) {
return list1;
}
int r = comp.compare(list1.get(0), list2.get(0));
if (r < 0) {
return list2;
} else if (r > 0) {
return list1;
} else {
list1.addAll(list2);
return list1;
}
});
}
The Collector will maintain an ArrayList to be used for the result, and accumulate each element into it, checking how the element compares to the first element of the current list. The part c = comp.compare(t, list.get(0))) == 0
will check if the element has the same max value, and if so will add it to the list.
Using Java8 Stream to find the highest values from map
You can get a single key via
Integer max=mapGroup.entrySet().stream().max(Map.Entry.comparingByValue()).get().getKey();
but unfortunately, there is no built-in function for getting all equivalent maximums.
The simplest, straight-forward solution is to find the maximum value first and retrieve all keys mapping to that value afterwards:
private List<Integer> testStreamMap(Map<Integer, Long> mapGroup) {
if(mapGroup.isEmpty())
return Collections.emptyList();
long max = mapGroup.values().stream().max(Comparator.naturalOrder()).get();
return mapGroup.entrySet().stream()
.filter(e -> e.getValue() == max)
.map(Map.Entry::getKey)
.collect(Collectors.toList());
}
Solutions for getting all maximum values of a stream in a single pass, are discussed in “How to force max() to return ALL maximum values in a Java Stream?”. You will see that single-pass solutions are much more complicated and not worth the effort if your input is an ordinary Map
(e.g. HashMap
), which can be iterated multiple times cheaply.
Get a list of object with max values
IF you want a single pipeline, you can group the Student
s by that property, and if you produce a TreeMap
for the output, it will be sorted, so you'll have access to the Set
corresponding with the max value:
return
this.students()
.stream()
.collect(Collectors.groupingBy(student -> student.getAssignedProjects().size(),
TreeMap::new,
Collectors.toSet()))
.lastEntry()
.getValue();
Of course, if the number of Student
s having the max value is small relative to the size of the input list, it would be inefficient to sort the grouped Student
s (which is what creating a TreeMap
would do). Your original code would be more efficient.
How to get the max by key of the result of groupingBy
There are several ways to get a map entry by max key:
- Use sorted map like
TreeMap
and then get uselastEntry
method:
TreeMap<Integer, List<Alien>> map = aliens.stream()
.filter(x -> x.pos[1] == SpaceInvaders.ship)
.collect(Collectors.groupingBy(
x -> x.pos[0], TreeMap::new, Collectors.toList()
));
System.out.println(map.lastEntry());
- (by Holger's comment) Use
Stream::max
returningOptional
result
aliens.stream()
.filter(x -> x.pos[1] == SpaceInvaders.ship)
.collect(Collectors.groupingBy(x -> x.pos[0])) // non-sorted map
.entrySet()
.stream()
.max(Map.Entry.comparingByKey()) // returns Optional<Map.Entry>
.ifPresent(System.out::println); // print entry with max key if available
- Sort entries of the
aliens
by key in reverse order and pick up only one entry:
aliens.stream()
.filter(x -> x.pos[1] == SpaceInvaders.ship)
.collect(Collectors.groupingBy(x -> x.pos[0])) // non-sorted map
.entrySet()
.stream()
.sorted(Map.Entry.<Integer, List<Alien>>comparingByKey().reversed())
.limit(1)
.forEach(System.out::println);
java 8 get elements with equal max number of occurences
In the first place, why do you start with a Stream<Character>
. You can start with an array of chars and then use the iteration to build up a map from char to count and in the meantime calculate the max value in the map while iterating. Then use this map and the max value intermediate result to get the final result. This approach just passes over the collection only twice. Here's how it looks given that you have a char[]
named chars
upfront.
final Map<Character, Integer> charCntMap = new HashMap<>();
int maxCnt = 0;
for (char c : chars) {
charCntMap.merge(c, 1, (a, b) -> a + b);
final int charCnt = charCntMap.get(c);
if (maxCnt < charCnt)
maxCnt = charCnt;
}
final int maxVal = maxCnt;
List<Character> maxOccuringChars = charCntMap.entrySet().stream()
.filter(e -> e.getValue().intValue() == maxVal)
.map(Map.Entry::getKey)
.collect(Collectors.toList());
Output:
[A, B]
Related Topics
How to Sort Map Values by Key in Java
Should I Instantiate Instance Variables on Declaration or in the Constructor
Convert JSON Array to Normal Java List
Understand the R Class in Android
How to Set Java_Home Path on Ubuntu
Eclipse Release Heap Back to System
Kafka - Broker: Group Coordinator Not Available
How to Call Method in Jar File with Terminal
Java Version Still Showing as 1.4 Linux
Httpservletrequest Get JSON Post Data
How to Convert an Arraylist Containing Integers to Primitive Int Array
How to Parse JSON Parsing Using Gson in Android
How to Use the Legacy Apache Http Client on Android Marshmallow
What's the Location of the Javafx Runtime Jar File, Jfxrt.Jar, on Linux
Connecting to Access Database from Linux
Best Way to Daemonize Java Application on Linux
In Linux, How to Execute Java Jar File with External Jar Files