在Java开发过程中经常会用到排序,尤其是数据可视化这一块几乎涉及到表格相关的接口都需要排序,通常都会使用Comparator.comparing()
来处理这种操作,简单好用。但是如果涉及到倒序,或者按照字段顺序去排序,那么就需要特别注意一点了。
常见用法
通常,我们是以如下方式进行排序的:
//stream resultList = dataList.stream().sorted(o -> Integer.parseInt(String.valueOf(o.get("id")))).collect(Collectors.toList()) //干脆只对集合排序 dataList.sort(Comparator.comparing(o -> String.valueOf(o.get("id"))));
这样编码通常是可以正常实用的,但是一旦遇到倒序和多种排序规则,那么如果简单地使用如下方式编写就会出现一个奇怪的错误:
dataList.sort(Comparator.comparing(o -> String.valueOf(o.get("id"))).reversed());
此时,idea则会提示o.get(“id”)这个错误。
解决办法
这种问题可以使用如下两种方式解决
指定类型
使用lambda表达式的时候,通常不会去指定变量的类型,在这里需要指定它的类型即可
dataList.sort(Comparator.comparing((Map<String,Object> o) -> String.valueOf(o.get("id"))).reversed());
此时就正常了。
Functional Interface
也可以使用函数式接口来解决这个错误
Function<Map<String, Object>, Integer> orderFunc = o -> Integer.parseInt(String.valueOf(o.get("id"))); dataList.sort(Comparator.comparing(orderFunc).reversed());
原因
查阅了一些资料,按道理起始不需要指定类型应该就可以,但是实际情况单一排序的情况下是可执行的,但是多种排序规则则不生效,感觉是Java lambda的一个小缺陷。当然,本次问题出现的原因应该可以解释如下:
Lambda 分为隐式类型(参数没有清单类型)和显式类型;方法引用分为精确(无重载)和不精确。当接收者位置的泛型方法调用具有 lambda 参数,并且无法从其他参数完全推断出类型参数时,您需要提供显式 lambda、精确方法引用、目标类型转换或显式类型见证泛型方法调用以提供继续所需的附加类型信息。
补充:
Function<Map<String, Object>, Integer> orderFunc = o -> Arrays.sort(array, Comparator.<int[]>comparingInt(arr -> arr[0]).thenComparingInt(arr -> arr[1]));
- 原地排序不需要使用 stream.
- 使用 comparingInt 而不是 comparing.
- 为 comparingInt 显示声明泛型参数<int[]> 而不是在 lambda 中 cast