2015-11-29 25 views
5

Sto provando a scrivere un metodo per ottenere la modalità di un Collection utilizzando un Comparator.Come scrivere un metodo di modalità utilizzando gli stream

Per favore qualcuno può mostrarmi quali cambiamenti devo fare per ottenere questo da compilare? Non voglio cambiare la firma.

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

Si scopre stavo solo usando la versione sbagliata. Questo non viene compilato utilizzando javac 1.8.0_25. Le esatte tre messaggi di errore sono:

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 

Tuttavia, ho dato aggiornato a javac 1.8.0_65 e compila perfettamente.

+3

I pensi di avere solo un cattivo ')'. Il tuo 'collect' dovrebbe terminare con' counting' con 3 ')' e uno in meno alla fine dell'intera istruzione. –

+0

Strange 'TreeMap treeMap = new TreeMap <>(); Impostare > entrySet = treeMap.entrySet(); 'nemmeno funziona (eclissi). Per me, il tuo lambda si divide in "" in quel passo e interrompe ogni ulteriore accesso alle voci. o http://ideone.com/jKd2Jb – zapl

+0

@SotiriosDelimanolis Grazie. Modificato. Ancora non si compila. –

risposta

4

Questo codice non viene compilato con javac precedente a Java 8u40. Se si vuole ancora per renderlo compatibile con le versioni javac meno recenti, è possibile introdurre un'altra variabile generico come questo:

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

Tra l'altro è possibile utilizzare Stream.max invece di reduce e Map.Entry.comparingByValue() comparatore di prezzi:

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