Java中的比较器链

2022-09-03 12:32:37

阅读Oracle关于接口的Java教程,其中给出了一个关于(扑克牌)的例子,我试图理解接口中的默认方法。这是链接,“在现有接口中集成默认方法”部分。现在在最后一节中,他们首先按等级对卡牌进行排序,然后按套装排序。给出了以下逻辑。假设使用的任何接口、函数或类都已定义,并且函数采用CardsortComparator

逻辑 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中包含的比较器接口和新的静态方法。现在我理解了类似的东西,它按等级排序,但是在阅读当时的比较文档之后,我无法理解如何返回实现上述逻辑1的比较器。它是否在内部构建类似于逻辑 1 中指定的构造?myDeck.sort(Comparator.comparing(Card::getRank))thenComparingif-else


答案 1

是的,它在内部创建了类似的东西,只是使用了更多的中间lambda。假设 您的 和 方法返回一些可比较类的实例,在您的情况下,您实际上拥有:getRankgetSuitRankSuit

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

答案 2

这是我的机器上的实现(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);
    };
}

所以是的,它本质上是如果其他(更确切地说,是三元运算符)。


推荐