2014-11-29 5 views
12
public class Test { 
    public static void main(String[] args) { 
     List<Pair<String, Integer>> list = new ArrayList<>(); 
     list.add(new Pair<>("1", 8)); 
     list.add(new Pair<>("3", 2)); 
     list.add(new Pair<>("2", 15)); 

     list.stream() 
      .sorted(Comparator.comparingInt(p -> p.v)) 
      .map(p -> p.k) 
      .forEach(System.out::println); 

    } 
} 

class Pair<K, V> { 
    K k; 
    V v; 
    public Pair(K k, V v) { 
     this.k = k; 
     this.v = v; 
    } 
} 

Ok, wie Sie verstanden dieser Code mein Paar Schlüssel aus dem niedrigsten Wert auf den höchsten zugehörigen druckt, damit ich die erwartete Ausgabe:Misunderstanding über Vergleicher in Java 8

So weit so gut. Nun wollte ich das Gegenteil tun, ich dachte, ich würde nur

list.stream() 
    .sorted(Comparator.comparingInt(p -> p.v).reversed()) 
    .map(p -> p.k) 
    .forEach(System.out::println); 

zu tun haben, aber ich bekomme einen Übersetzungsfehler:

v cannot be resolved or is not a field 

So scheint es, wie comparingInt ein Comparator<Object> zurück. Warum es so? Sollte es nicht eine Comparator<Integer> zurückgeben?

Diese sind beide reproduzierbar mit Eclipse Luna Version 1 und javac.

javac -version => 1.8.0 
java -version => java version "1.8.0_25" 

Oh auch frei fühlen Sie den Titel meiner Frage ändern Sie es zu allgemein finden, aber ich konnte die richtigen Begriffe

+0

Es wird wahrscheinlich mit Comparator.reverseOrder funktionieren. – assylias

+0

@assy lias Nun, wie würde ich das mit ReverseOrder erreichen? Es würde bedeuten, dass meine Paarobjekte bereits vergleichbar sind. – user2336315

+0

Beantwortet hier: http://StackOverflow.com/Questions/25172595/Comparator-Reversed-Not-Compiles-Wusting-Lambda –

Antwort

8

Ich glaube, es ist nur, dass Typinferenz versagt, im Grunde nicht gefunden - weil der Aufruf reverse() den erwarteten Argumenttyp von sorted() und den Lambda-Ausdruck in den Weg stellt.

Sie können es tun, wenn Sie den Typ comparingInt explizit angeben:

list.stream() 
    .sorted(Comparator.<Pair<String, Integer>>comparingInt(p -> p.v).reversed()) 
    .map(p -> p.k) 
    .forEach(System.out::println); 

Oder wenn Sie nur die comparer erklären zuerst:

Comparator<Pair<String, Integer>> forward = Comparator.comparingInt(p -> p.v); 
list.stream() 
    .sorted(forward.reversed()) 
    .map(p -> p.k) 
    .forEach(System.out::println); 

Es fühlt sich für mich wie sollte es eine Stream.reverseSorted sein machen Sie diese Art von Sache wirklich einfach, aber es sieht nicht aus wie es existiert :(

+0

... was ziemlich hässlich ist, dann bevorzuge ich 'sortierte ((p1, p2) -> p2.v.compareTo (p1.v))'. Also ist es wahrscheinlich ein Fehler im Compiler? – user2336315

+4

@ user2336315: Ich stimme zu, es ist hässlich - aber das heißt nicht, dass es ein Fehler im Compiler ist. Ich glaube, es ist eine Beschränkung der Typinferenz in der Sprache, die nicht dasselbe ist. Um ehrlich zu sein, ich habe nie verstanden, wie generische Typinferenz in Java funktioniert (und ich glaube, dass es sich an einigen Stellen im Laufe der Zeit geändert hat) - aber das ist definitiv eine einfache Einschränkung für mich. –

+0

Ah ich sehe. Vielleicht wird dies in einer zukünftigen Version verbessert werden. Ich weiß, dass sie schon einige Verbesserungen gemacht haben, deshalb fand ich es seltsam, dass es nicht kompiliert wurde ... :( – user2336315