Java8新增了lambda表达式以及方法引用。使得排序有了更方便的表达。以下均以字符串数组为例。
String[] planets = new String[] { "Mercury", "Venus", "Earth", "Mars",
"Jupiter", "Saturn", "Uranus", "Neptune" };
一、由于String类实现了Comparable接口,使用单参数的sort方法会自动按字典序排序。
//默认的字典序
Arrays.sort(planets);
二、按照字符串长度排序,由于String不可变且为final,不可能重写其compareTo方法,故使用双参数形式的sort方法。
第二个参数需要一个Comparator对象,我们只需构造一个实现Comparator的类即可。
class comp implements Comparator<String>
{
public int compare(String a,String b)
{
return a.length()-b.length();
}
}
//字符长度排序——Comparator对象
Arrays.sort(planets,new comp());
三、第二类为最万金油的方法,但非常繁琐,你需要实现一个类,还要实现一个抽象方法。在Java8下有了函数式接口和lambda表达式,可以简化操作。
函数式接口:只有一个抽象方法的接口。
lambda表达式:一个代码块,参数,自由变量(非参数且不在该代码块中定义的变量,该变量初始化后就不会为它赋新值)
形式:(形参)-> 表达式/代码块
如果可以推导出形参的类型,可以不写;如果只有一个参数且该参数类型可推导,小括号也可省略;
无需指定返回类型,自动推导。
Waring:如果一个lambda表达式只在某些分支返回值,而在另一分支不返回值是不合法的。
//字符长度排序——lambda表达式
Arrays.sort(planets, (first, second) -> first.length() - second.length());
四、方法引用
这个没有完全懂。。应该相当于c++的函数指针?反正等价于对应的lambda表达式。用 ::分隔方法名与对象或类名
//忽视大小写字典序排序——方法引用
Arrays.sort(planets,String::compareToIgnoreCase);
在这里 String::compareToIgnoreCase等价于 (x,y) -> x.compareToIgnoreCase(y)
方法引用主要有3中情况:
1. object::instanceMethod
2.Class::staticMethod
3.Class::instanceMethod
前两种情况下,方法引用等价于提供方法参数的lambda表达式
比如 Math::pow 等价于(x,y) -> Math.pow(x,y)
最后一种情况,带一个参数会成为方法的目标(this)
比如这里的 String::compareToIgnoreCase等价于 (x,y) -> x.compareToIgnoreCase(y)
同样的,可以在方法引用中使用this与super(效果等同于上述的第一种和第二种)
五、comparing方法
Comparing接口有一个静态的comparing方法,可以用于lambda表达式或方法引用
//先按长度排序,再按哈希码排序————方法引用
Arrays.sort(planets,Comparator.comparing(String::length).thenComparing(String::hashCode));
comparing有多种变体,比如thenComparing(第二排序标准,直接跟在comparing后面就行了),
comparingInt(比较int值使用,可以避免int类型装箱成Integer类再调用comparing方法)等
//先按长度排序,再按字典序排序————lambda
Arrays.sort(planets,Comparator.comparingInt((String p)->p.length()).thenComparing(p->p));
System.out.println(Arrays.toString(planets));
其实还有一个使用适配器与比较器的方法,来处理某些情况下比较的key为null的情况,不过我看不懂了,以后再补
本篇红字部分来自 corejava