比较器链在java中

abk*_*kds 10 java comparator java-8

在接口上阅读Oracle教程,Card(扑克牌)上给出一个例子,我试图理解接口中默认方法.这是链接 "在现有接口中集成默认方法"部分.现在在最后一节中,他们首先按照等级然后按套装对卡片进行排序.已经给出了逻辑.假设已经定义了所使用的任何接口,函数或类,并且sort函数需要aComparator

逻辑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(); 
    }
}
Run Code Online (Sandbox Code Playgroud)

逻辑2:

myDeck.sort(
    Comparator
        .comparing(Card::getRank)
        .thenComparing(Comparator.comparing(Card::getSuit)));
Run Code Online (Sandbox Code Playgroud)

现在我在理解第二个逻辑时遇到了一些问题.我阅读了比较器接口和Java 1.8中包含的新静态方法.现在我理解类似于myDeck.sort(Comparator.comparing(Card::getRank))按排名排序但是在阅读完文档thenComparing之后,我无法理解thenComparing返回a 如何Comparator实现上述逻辑1.它是否在内部构建类似于if-else逻辑1中指定的构造?

Red*_*ins 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);
    };
}
Run Code Online (Sandbox Code Playgroud)

所以是的,它本质上是if else(更准确地说,是三元运算符).

  • @AbKDs,在JDK安装中的src.zip文件中.或[在线](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/Comparator.java#Comparator.thenComparing%28java.util.Comparator %29). (3认同)

Tag*_*eev 10

是的,它在内部产生了类似的东西,只有更多的中间lambda.假设你getRankgetSuit方法返回可比类的一些实例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);
};
Run Code Online (Sandbox Code Playgroud)

内联后(可能由JIT编译器执行)你可能有这样的东西:

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

请注意,您可以使用更简单的版本:

myDeck.sort(
    Comparator
        .comparing(Card::getRank)
        .thenComparing(Card::getSuit));
Run Code Online (Sandbox Code Playgroud)