I am trying to write a method to get the mode of a Collection
using a Comparator
.
Please can somebody show me what changes I have to make to get this to compile? I do not want to change the signature.
static <T> T mode(Collection<? extends T> collection, Comparator<? super T> comparator) {
return collection.stream()
.collect(Collectors.groupingBy(t -> t, () -> new TreeMap<>(comparator), Collectors.counting()))
.entrySet()
.stream()
.reduce(BinaryOperator.maxBy(Comparator.comparingLong(Map.Entry::getValue)))
.map(Map.Entry::getKey)
.orElseThrow(IllegalArgumentException::new);
}
EDIT
It turns out I was just using the wrong version. This does not compile using javac 1.8.0_25
. The exact three error messages are:
Error:(40, 47) java: incompatible types: inferred type does not conform to upper bound(s)
inferred: java.lang.Object
upper bound(s): T,java.lang.Object
Error:(43, 45) java: incompatible types: cannot infer type-variable(s) T
(argument mismatch; invalid method reference
method getValue in interface java.util.Map.Entry<K,V> cannot be applied to given types
required: no arguments
found: java.lang.Object
reason: actual and formal argument lists differ in length)
Error:(44, 25) java: invalid method reference
non-static method getKey() cannot be referenced from a static context
However, I have since upgraded to javac 1.8.0_65
and it compiles perfectly.
This code does not compile with javac prior to Java 8u40. If you still want to make it compatible with older javac versions, you can introduce another generic variable like this:
static <T> T mode(Collection<? extends T> collection, Comparator<? super T> comparator) {
return mode0(collection, comparator);
}
private static <T, TT extends T> T mode0(Collection<TT> collection,
Comparator<? super T> comparator) {
return collection.stream()
.collect(Collectors.groupingBy(t -> t,
() -> new TreeMap<>(comparator),
Collectors.counting()))
.entrySet()
.stream()
.reduce(BinaryOperator.maxBy(
Comparator.comparingLong(Map.Entry::getValue)))
.map(Map.Entry::getKey)
.orElseThrow(IllegalArgumentException::new);
}
By the way you may use Stream.max
instead of reduce
and Map.Entry.comparingByValue()
comparator:
private static <T, TT extends T> T mode0(Collection<TT> collection,
Comparator<? super T> comparator) {
return collection.stream()
.collect(Collectors.groupingBy(t -> t,
() -> new TreeMap<>(comparator),
Collectors.counting()))
.entrySet()
.stream()
.max(Map.Entry.comparingByValue())
.map(Map.Entry::getKey)
.orElseThrow(IllegalArgumentException::new);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With