2015-08-25 10 views
5

Przeczytanie Java Tutorial by Oracle on interfaces, który daje przykład na Card (karty do gry) Próbowałem zrozumieć default methods in interfaces. Oto sekcja link "Integrowanie domyślnych metod w istniejących interfejsach". Teraz w ostatniej sekcji posortowali karty według rangi, a następnie według kolorów. Podano następujące logiki. Załóżmy, że cokolwiek interfejsy, funkcje lub klasy, które są użyte zostały zdefiniowane i sort funkcja przyjmuje ComparatorŁańcuch komparatorów w java

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

Teraz mam pewne problemy w zrozumieniu drugiej logiki. Przeczytałem interfejsy komparatora i nowe metody statyczne, które zostały zawarte w Java 1.8. Teraz rozumiem coś takiego myDeck.sort(Comparator.comparing(Card::getRank)) który sortuje według rangi, ale po przeczytaniu the documentation for thenComparing, nie jestem w stanie zrozumieć, jak thenComparing zwraca Comparator który spełnia powyższe Logic 1. Czy wewnętrznie zbudować coś jak if-else konstruktu, jak określono w Logic 1?

Odpowiedz

6

Tak, tworzy wewnętrznie coś podobnego, tylko z bardziej pośrednimi lambdami. Zakładając, że getRank i getSuit metody wrócić kilka wystąpień porównywalnych klasach Rank i Suit, w przypadku, gdy faktycznie mają:

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

Więc po inline (które mogą być wykonywane przez JIT kompilatora) może mieć coś takiego :

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

Zauważ, że można użyć prostszej wersji:

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

Jest to realizacja na moim komputerze (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); 
    }; 
} 

tak tak, to jest w istocie, jeśli inny (bardziej precyzyjnie, operator trójargumentowy).

+0

Wh Czy możemy sprawdzić kod źródłowy Oracle JDK? – AbKDs

+1

My IDE (IntelliJ) ściąga to dla mnie. Na moim Macu jest to: /Library/Java/JavaVirtualMachines/jdk1.8.0_40.jdk/Contents/Home/src.zip!/java/util/Comparator.java – RedDeckWins

+3

@AbKDs, w pliku src.zip wewnątrz instalacji JDK . Lub [online] (http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/Comparator.java#Comparator.thenComparing%28java.util.Comparator % 29). –