2015-11-29 3 views
5

Ich versuche, eine Methode zu schreiben, um den Modus einer Collection mit einem Comparator zu erhalten.Wie schreibe ich eine Mode-Methode mit Streams

Kann mir bitte jemand zeigen, welche Änderungen ich machen muss, um das kompilieren zu lassen? Ich möchte die Signatur nicht ändern.

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

Es stellt sich heraus, dass ich die falsche Version nur wurde mit. Dies kompiliert nicht mit javac 1.8.0_25. Die genauen drei Fehlermeldungen sind:

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 

Allerdings habe ich zu javac 1.8.0_65 da ein Upgrade und es kompiliert perfekt.

+3

I denke du hast nur ein schlechtes ')'. Ihre 'collect' sollte mit' '' '' '' '' und am Ende der gesamten Anweisung mit einem '' Count '' enden. –

+0

Seltsame 'TreeMap treeMap = neue TreeMap <>(); Stellen Sie > entrySet = treeMap.entrySet(); 'funktioniert nicht einmal (Eclipse). Bei mir bricht Ihr Lambda in diesem Schritt auf "" ab und stoppt alle weiteren Zugriffe auf die Einträge. oder http://ideone.com/jKd2Jb – zapl

+0

@StiriosDelimanolis Danke. Bearbeitet. Es kompiliert immer noch nicht. –

Antwort

4

Dieser Code wird nicht mit Java vor Java 8u40 kompiliert. Wenn Sie immer noch kompatibel mit älteren Javac Versionen machen wollen, können Sie eine andere generische Variable wie folgt vorstellen:

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); 
} 

Durch die Art und Weise Sie Stream.max statt reduce und Map.Entry.comparingByValue() Komparator verwenden:

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); 
} 
Verwandte Themen