2015-08-25 8 views
5

Lesen der Java Tutorial by Oracle on interfaces, die ein Beispiel gibt auf Card (Spielkarten) Ich habe versucht, die default methods in interfaces zu verstehen. Hier ist die link, Abschnitt "Integration von Standardmethoden in bestehende Schnittstellen". Im letzten Abschnitt sortierten sie die Karten zuerst nach Rang und dann nach Anzügen. Folgende Logiken wurden angegeben. Nehmen wir an, was auch immer Schnittstellen, Funktionen oder Klassen, die verwendet werden, definiert und sort Funktion nimmt einen ComparatorKette von Komparatoren in Java

Logik 1:

package defaultmethods; 

import java.util.*; 
import java.util.stream.*; 
import java.lang.*; 

public class SortByRankThenSuit implements Comparator<Card> { 
    public int compare(Card firstCard, Card secondCard) { 
     int compVal = 
      firstCard.getRank().value() - secondCard.getRank().value(); 
     if (compVal != 0) 
      return compVal; 
     else 
      return firstCard.getSuit().value() - secondCard.getSuit().value(); 
    } 
} 

Logic 2:

myDeck.sort(
    Comparator 
     .comparing(Card::getRank) 
     .thenComparing(Comparator.comparing(Card::getSuit))); 

Jetzt habe ich einige Probleme habe im Verständnis der zweiten Logik. Ich lese die Komparator-Schnittstellen und die neuen statischen Methoden, die in Java 1.8 enthalten sind. Jetzt verstehe ich etwas wie diese myDeck.sort(Comparator.comparing(Card::getRank)) die nach Rang sortiert, aber nach dem Lesen the documentation for thenComparing, kann ich nicht verstehen, wie thenComparing eine Comparator zurückgibt, die die obige Logik erreicht 1. Baut es intern etwas wie die if-else Konstrukt wie in Logic 1 angegeben?

Antwort

6

Ja, es schafft intern etwas ähnliches, nur mit mehr intermediären Lambdas. Unter der Annahme, dass Ihr getRank und getSuit Methoden einige Beispiele vergleichbarer Klassen zurückkehren Rank und Suit, in Ihrem Fall, dass Sie effektiv haben:

Function<Card, Rank> toRank = Card::getRank; 
Comparator<Card> comp1 = (a, b) -> toRank.apply(a).compareTo(toRank.apply(b)); 
Function<Card, Suit> toSuit = Card::getSuit; 
Comparator<Card> comp2 = (a, b) -> toSuit.apply(a).compareTo(toSuit.apply(b)); 
Comparator<Card> result = (a, b) -> { 
    int res = comp1.compare(a, b); 
    return res != 0 ? res : comp2.compare(a, b); 
}; 

So nach inlining (die durch JIT-Compiler ausgeführt werden könnte), die Sie so etwas wie dieses haben :

Comparator<Card> result = (a, b) -> { 
    int res = a.getRank().compareTo(b.getRank()); 
    return res != 0 ? res : a.getSuit().compareTo(b.getSuit()); 
}; 

Beachten Sie, dass die einfachere Version verwenden können:

myDeck.sort(
    Comparator 
     .comparing(Card::getRank) 
     .thenComparing(Card::getSuit)); 
10

Dies ist die Implementierung auf meinem Rechner (Oracle JDK 8u40)

default Comparator<T> thenComparing(Comparator<? super T> other) { 
    Objects.requireNonNull(other); 
    return (Comparator<T> & Serializable) (c1, c2) -> { 
     int res = compare(c1, c2); 
     return (res != 0) ? res : other.compare(c1, c2); 
    }; 
} 

also ja, es im Wesentlichen, wenn sonst ist (genauer gesagt, der ternäre Operator).

+0

Wh Können wir den Quellcode von Oracle JDK überprüfen? – AbKDs

+1

Meine IDE (IntelliJ) zieht es für mich ein. Auf meinem Mac befindet es sich in: /Library/Java/JavaVirtualMachines/jdk1.8.0_40.jdk/Contents/Home/src.zip!/java/util/Comparator.java – RedDeckWins

+3

@AbKDs, in der Datei src.zip in Ihrer JDK-Installation . Oder [online] (http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/Comparator.java#Comparator.thenComparing%28java.util.Comparator % 29). –