Reputation: 1187
Stream<Integer> stream = Stream.of(2, 1, 3, 4, 2, 3, 2);
If the occurence of the numbers is more, then display that number ,so result is 2
Stream<Integer> stream = Stream.of(2, 1, 3, 4, 2, 3);
If the occurence of the numbers are same for multiple numbers ,then fetch maximum number so result is 2
Optional<Map.Entry<Integer, Long>> sorted1 = stream.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet().stream().filter(k -> k.getValue() > 1).max(Comparator.comparing(Map.Entry::getValue));
I have written above logic but not able to fetch both results.
Upvotes: 0
Views: 203
Reputation: 22977
It's also possible to write a custom collector, which is able to collect the highest frequencies in one pass.
class HighestFrequencyContainer {
// Keep track of the highest frequency
private long highestFrequency;
// Keep track of the objects with the highest frequency
private final Set<T> objectsWithHighestFrequency = new HashSet<>();
// Keep track of all objects along with their frequencies
private final Map<T, Long> map = new HashMap<>();
// Make sure you can add an object
public void add(T object) { ... }
// Make sure this container can be merged with another one. We'll utilize this
// method when we create a custom collector.
public HighestFrequencyContainer<T> merge(HighestFrequencyContainer<T> container) { ... }
// Make sure we can get a Set with all objects with the highest frequency
public Set<T> highestFrequencies() {
return Set.copyOf(objectsWithHighestFrequency);
}
}
Then we'll write a collector which utilizes the abovementioned class:
// Creates a Collector returning a Set<T> with all objects with the highest frequency
public static <T> Collector<T, ?, Set<T>> highestFrequency() {
Collector<T, ?, HighestFrequencyContainer<T>> collector = Collector.of(HighestFrequencyContainer::new, HighestFrequencyContainer::add, HighestFrequencyContainer::merge);
return Collectors.collectingAndThen(collector, HighestFrequencyContainer::highestFrequencies);
}
At last, we can retrieve the set using
Stream<Integer> stream = Stream.of(2, 1, 3, 4, 2, 3);
Set<Integer> set = stream.collect(MoreCollectors.highestFrequency());
Now the set contains {2, 3}
, because those two numbers have the highest frequency (which is 2).
To select the highest number, use a TreeSet
:
Integer result = new TreeSet<>(set).pollFirst();
Upvotes: 0
Reputation: 6650
Use .thenComparing ()
in order to sort by value among those which have the same count.
Optional<Entry<Integer, Long>> sorted1 = Stream.of (1, 2, 2, 3, 1)
.collect (Collectors.groupingBy (Function.identity (), Collectors.counting ()))
.entrySet ()
.stream ()
.filter (k -> k.getValue () > 1)
.max (Comparator.<Map.Entry<Integer, Long>, Long>comparing (Map.Entry::getValue)
.thenComparing (Map.Entry::getKey)
);
NB: If you’re only interested in the value, not the count, add .map (Map.Entry::getKey)
at the end.
NB: The line filter (k -> k.getValue () > 1)
means you’ll get an empty optional for input such as [1] or [1, 2, 3], which may or may not be what you want (dropping it would result in respectively 1 and 3).
Upvotes: 5