使用lambda代替显式类

时间:2018-07-18 17:00:19

标签: java lambda comparator

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

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

但是我没有完整列表(没有Ralph Smith:-19.08)。 有谁知道怎么写?谢谢。

UPD:

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

2 个答案:

答案 0 :(得分:5)

您将需要重新实现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文档。)

答案 1 :(得分:2)

正如@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));