8

在 Java 8 之前,我们Comparable.compareTo(...)是这样实现的:

public int compare(Person a, Person b) {
    return new CompareToBuilder()
            .append(a.getLastName(), b.getLastName())
            .append(a.getFirstName(), b.getFirstName())
            .toComparison();
}

从 Java 8 开始,我们可以这样做:

public int compare(Person a, Person b) {
    return Comparator
            .comparing(Person::getLastName)
            .thenComparing(Person::getFirstName)
            .compare(a, b);
}

新的 Java 8 方式可能允许我们删除commons-lang3依赖项。新的 Java 8 速度更快吗?有没有办法自动迁移?我没有找到 IntelliJ 的意图。


请注意,当存在反向顺序并且涉及非自然比较时,它会变得更加复杂:

public int compare(SingleBenchmarkResult a, SingleBenchmarkResult b) {
    return new CompareToBuilder()
            .append(b.hasAnyFailure(), a.hasAnyFailure()) // Reverse
            .append(a.getAverageScore(), b.getAverageScore(), resilientScoreComparator)
            .toComparison();
}

变成

public int compare(SingleBenchmarkResult a, SingleBenchmarkResult b) {
    return Comparator
            .comparing(SingleBenchmarkResult::hasAnyFailure, Comparator.reverseOrder()) // Reverse
            .thenComparing(SingleBenchmarkResult::getAverageScore, resilientScoreComparator)
            .compare(a, b);
}
4

2 回答 2

8

如果你这样写

public int compare(Person a, Person b) {
    return Comparator
            .comparing(Person::getLastName)
            .thenComparing(Person::getFirstName)
            .compare(a, b);
}

您通过Comparator为每个比较构建一个新的来浪费性能。并且在查看周围的代码时应该显然是无意义的。该compare(Person a, Person b)方法肯定是实现类的一部分Comparator<Person>,您可以在某个地方对其进行实例化以获得所需的比较器。您应该将该Comparator.comparing(Person::getLastName).thenComparing(Person::getFirstName)实例替换为在整个操作中使用的唯一实例。

例如

// reusable
static final Comparator<Person> By_NAME = Comparator
             .comparing(Person::getLastName).thenComparing(Person::getFirstName);

或临时的

listOfPersons.sort(Comparator.comparing(Person::getLastName)
                             .thenComparing(Person::getFirstName));

如果您以这种方式使用它,它很可能会更快。但是,您应该看到,不可能有简单的基于模式的替换。您必须用那个简单的声明性构造替换类的使用站点,并决定是为多个使用站点使用共享比较器实例还是临时创建它。然后,您可以删除整个旧实现类,或者至少,如果它仍然用于其他目的,则从中删除比较器功能。

于 2016-07-04T12:36:50.083 回答
3

我认为没有任何预定义的检查。您可能会尝试使用 IntelliJ 的结构搜索,尽管我认为对每种可能的情况都这样做可能非常棘手。具有两个比较的简单案例的一种可能性可能如下:

搜索模板($TYPE$和的出现次数$z$为2):

$ReturnType$ $MethodName$($TYPE$ $z$) {
        return new CompareToBuilder()
                .append($A$.$m$(), $B$.$m$())
                .append($A$.$m1$(), $B$.$m1$())
                .toComparison();
    }

替换模板:

$ReturnType$ $MethodName$($TYPE$ $z$) {
    return java.util.Comparator
            .comparing($TYPE$::$m$)
            .thenComparing($TYPE$::$m1$)
            .compare($A$, $B$);
}

我不是结构搜索方面的专家,但我想您必须为具有或多或少比较的调用创建另一种模式。

于 2016-07-04T08:12:05.343 回答