How to write a mode method using streams

I am trying to write a method to get the Collection method using Comparator .

Please someone show me what changes I need 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

Turns out I just used the wrong version. This will not compile with 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, since then I upgraded to javac 1.8.0_65 and it compiles fine.

+5
source share
1 answer

This code does not compile with javac until Java 8u40. If you still want to make it compatible with older versions of javac, you can enter another common variable:

 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 can 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); } 
+4
source

Source: https://habr.com/ru/post/1237030/


All Articles