Comparator.comparing(keyExtractor).reverse()引发的泛型问题

背景

有一个Map<String, String>组成的列表mapList,需要根据每个mapname值倒序排序。

创建一个根据Map<String, String>name值倒序排序的Comparator

如果正序排序,可以这样写:

mapList.sort(Comparator.comparing(map -> map.get("name")));

但是如果倒序直接这样写,是会报错的:

mapList.sort(Comparator.comparing(map -> map.get("name")).reverse()); // 错误

报错:Cannot resolve method 'get' in 'Object',可以看出是变量map被当做Object了。

原因

其实问题的根源在泛型问题上。先看这一句:

Comparator.comparing(map -> map.get("name"));

如果单独这么写一句,是会报错的,原因是不知道变量map的类型,自然会将其当做Object,无法调用get方法。

要明确指出变量map的类型,有三种方法:

// 方法1:显式声明lambda
Function<Map<String, String>, String> keyExtractor = map -> map.get("name");
Comparator.comparing(keyExtractor);

方法1先声明了keyExtractor的类型,明确指出了参数的类型。

// 方法2:指定Comparator的类型
Comparator<Map<String, String>> comparator = Comparator.comparing(map -> map.get("name"));

方法2指定了返回的Comparator的类型,也能确定参数的类型。

comparing函数的声明如下:

public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
            Function<? super T, ? extends U> keyExtractor) {...}

可以看到泛型T在返回值和参数中都出现,因此明确指定其中一个即可将其确定。

背景中的正序排序写法其实也是指定了返回值的类型,因为mapList.sort()的参数一定是Comparator<Map<String, String>>

而倒序排序的写法在comparing的返回值调用了reverse(),就变成了返回值和参数都没指定类型,无法确定map的类型了。

// 方法3:强制转换lambda的类型
Comparator.comparing((Function<Map<String, String>, String>) map -> map.get("name"));

方法3通过强制转换确定了comparing函数参数的类型。

结论

// 倒序排序:实际使用中,建议写两行
mapList.sort(Comparator.comparing(map -> map.get("name")));
Collections.reverse(mapList);
// 如果想一行搞定,需要这么写
mapList.sort(Comparator.comparing((Function<Map<String, String>, String>) map -> map.get("name")).reverse());
// 顺带一提,如果是调用对象方法的话,用方法引用也可以搞定
userList.sort(Comparator.comparing(User::getName).reversed());
  • 16
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值