使用 lambdas 而不是显式 类

Usage of lambdas instead of explicit classes

我有程序使用显式 类 对值进行排序:

class CompLastNames implements Comparator<String> {
    public int compare(String aStr, String bStr) {
        int i, j;

        i = aStr.lastIndexOf(' ');
        j = bStr.lastIndexOf(' ');
        return aStr.substring(i).compareToIgnoreCase(bStr.substring(j));
    }
}

class CompThenByFirstName implements Comparator<String> {
    public int compare(String aStr, String bStr) {
        int i, j;

        return aStr.compareToIgnoreCase(bStr);
    }
}

public class TreeMapDemo2A {
    public static void main(String[] args) {

        CompLastNames compLN = new CompLastNames();
        Comparator<String> compLastThenFirst = 
                compLN.thenComparing(new CompThenByFirstName());

        TreeMap<String, Double> tm = 
                new TreeMap<String, Double>(compLastThenFirst);
...

Full code

得到结果:

Jane Baker: 1378.0
John Doe: 3434.34
Ralph Smith: -19.08
Tom Smith: 123.22
Tod Hull: 99.22

The new account balance of John Doe: 4434.34

然后,我尝试添加 lambda 而不是显式 类,例如:

Comparator<String> compLastThenFirst = 
                ((aStr, bStr) -> aStr.compareToIgnoreCase(bStr));

        TreeMap<String, Double> tm = 
                new TreeMap<String, Double>((aStr, bStr) -> aStr.substring(aStr.lastIndexOf(' ')).compareToIgnoreCase(bStr.substring(bStr.lastIndexOf(' '))));

Full code

结果是:

Jane Baker: 1378.0
John Doe: 3434.34
Tom Smith: -19.08
Tod Hull: 99.22

The new account balance of John Doe: 4434.34

但我没有得到完整列表 (没有拉尔夫·史密斯:-19.08)。 有谁知道如何正确书写?谢谢。

更新:

1)

Comparator<String> compLastThenFirst =
            ((Comparator<String>) (a, b) -> a.substring(a.lastIndexOf(' ')).compareToIgnoreCase(b.substring(b.lastIndexOf(' '))))
            .thenComparing((a, b) -> a.compareToIgnoreCase(b));

    TreeMap<String, Double> tm = 
            new TreeMap<String, Double>(compLastThenFirst);
    ...

2)

Comparator<String> compLN = (aStr, bStr) ->
        aStr.substring(aStr.lastIndexOf(' '))
            .compareToIgnoreCase(bStr.substring(bStr.lastIndexOf(' ')));
Comparator<String> compLastThenFirst = 
        compLN.thenComparing((aStr, bStr) -> aStr.compareToIgnoreCase(bStr));


        TreeMap<String, Double> tm = 
                new TreeMap<String, Double>(compLastThenFirst);
    ...

正如@Sweeper 在评论中提到的,您忘记了对 Comparator#thenComparing 的调用。与 lambda 表达式对应的代码为:

Comparator<String> compLastThenFirst =
        ((Comparator<String>) (a, b) -> a.substring(a.lastIndexOf(' ')).compareToIgnoreCase(b.substring(b.lastIndexOf(' '))))
        .thenComparing((a, b) -> a.compareToIgnoreCase(b));

您需要重新实现 thenComparing(Comparator) 所做的事情:

(aStr, bStr) -> {
    int compareResult =
        aStr.substring(aStr.lastIndexOf(' '))
            .compareToIgnoreCase(
                bStr.substring(bStr.lastIndexOf(' '))
            )
    if (compareResult != 0)
        compareResult = aStr.compareToIgnoreCase(bStr);
    return compareResult;
}

(还有see the OpenJDK source code。)

或者您可以通过分配给临时变量来使用 thenComparing(如第一个示例):

Comparator<String> compLN = (aStr, bStr) ->
        aStr.substring(aStr.lastIndexOf(' '))
            .compareToIgnoreCase(bStr.substring(bStr.lastIndexOf(' ')));
Comparator<String> compLastThenFirst = 
        compLN.thenComparing((aStr, bStr) -> aStr.compareToIgnoreCase(bStr));

然而,最简单的写一个比较器的方法可能是这样的,使用comparing(Function,Comparator):

Comparator.comparing(str -> str.substring(str.lastIndexOf(' ')),
                     String.CASE_INSENSITIVE_ORDER)
          .thenComparing(String.CASE_INSENSITIVE_ORDER)

(另请参阅 String.CASE_INSENSITIVE_ORDER 文档。)