阅读Java Tutorial by Oracle on interfaces,其中提供了Card
(扑克牌)的示例,我试图理解default methods in interfaces。这是link,部分"在现有界面中集成默认方法"。现在在最后一节中,他们首先按照等级然后按套装对卡片进行排序。已经给出了逻辑。假设已经定义了所使用的任何接口,函数或类,并且sort
函数需要Comparator
逻辑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();
}
}
逻辑2:
myDeck.sort(
Comparator
.comparing(Card::getRank)
.thenComparing(Comparator.comparing(Card::getSuit)));
现在我在理解第二个逻辑时遇到了一些问题。我阅读了比较器接口和Java 1.8中包含的新静态方法。现在我理解类似myDeck.sort(Comparator.comparing(Card::getRank))
的排序按排名排序但在阅读the documentation for thenComparing
之后,我无法理解thenComparing
如何返回实现上述逻辑1的Comparator
。它在内部构建类似于逻辑1中指定的if-else
构造的东西吗?
答案 0 :(得分:11)
这是我的机器上的实现(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);
};
}
所以是的,它基本上是if else(更准确地说,是三元运算符)。
答案 1 :(得分:9)
是的,它在内部创造了类似的东西,只有更多的中间lambda。假设您的getRank
和getSuit
方法返回了一些类似的类Rank
和Suit
的实例,在您的情况下,您实际上有:
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);
};
所以在内联之后(可能由JIT编译器执行)你可能会有这样的事情:
Comparator<Card> result = (a, b) -> {
int res = a.getRank().compareTo(b.getRank());
return res != 0 ? res : a.getSuit().compareTo(b.getSuit());
};
请注意,您可以使用更简单的版本:
myDeck.sort(
Comparator
.comparing(Card::getRank)
.thenComparing(Card::getSuit));