一、实体类
public class Employe {
private String name;
private int age;
private double salary;
public Employe() {
}
public Employe(String name, int age, double salary) {
this.name = name;
this.age = age;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
@Override
public String toString() {
return "Employe{" +
"name='" + name + '\'' +
", age=" + age +
", salary=" + salary +
'}';
}
}
二、Lambda表达式语法
Lambda 是一个匿名函数,可以把Lambda表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。可以写出更简洁、更灵活的代码。Java8引入了一个新的操作符 “->” 该操作符称为箭头符或lambda 操作符,箭头操作符将 Lambda 表达式拆分成两部分:左侧:Lambda 表达式的参数列表;右侧:Lambda 表达式中所需要执行的功能,即 Lambda 体;
public class TestLambda {
//原来匿名内部类
@Test
public void test1(){
Comparator<Integer> com = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return Integer.compare(o1, o2);
}
};
TreeSet<Integer> ts = new TreeSet<>(com);
}
//Lambda表达式
@Test
public void test2(){
Comparator<Integer> com = (o1, o2) -> Integer.compare(o1, o2);
TreeSet<Integer> ts = new TreeSet<>(com);
}
}
/**
* Lambda表达式练习
*/
public class TestLambda1 {
List<Employe> emps = Arrays.asList(
new Employe("张三", 18,9999.99),
new Employe("李四", 38,5555.99),
new Employe("王五", 50,6666.66),
new Employe("赵六", 16,3333.33),
new Employe("田七", 10,7777.77),
new Employe("田八", 10,7777.77)
);
//需求:按员工年龄排序,年龄相同按姓名排序
@Test
public void test1(){
Collections.sort(emps, (x, y) -> {
if (x.getAge() == y.getAge()){
return x.getName().compareTo(y.getName());
}else{
return -Integer.compare(x.getAge(),y.getAge());
}
});
emps.forEach(System.out::println);
}
}
三、Java8中内置的四大核心函数式接口
/**
* java8 内置的四大核心函数式接口
*
* 1.Consumer<T>:消费型接口
* void accept(T t);
*
* 2.Supplier<T>: 供给型接口
* T get();
*
* 3.Function<T, R>:函数型接口
* R apply(T t);
*
* 4.Predicate<T>:断言型接口
* boolean test(T t);
*
*/
public class TestLambda3 {
//Consumer<T>:消费型接口
@Test
public void test1(){
happy(1000, m-> System.out.println("吃饭消费:"+m));
}
public void happy(double money, Consumer<Double> con){
con.accept(money);
}
//Supplier<T>: 供给型接口
@Test
public void test2(){
List<Integer> list = getNumList(10, () -> (int)(Math.random() * 100));
list.forEach(System.out::println);
}
//需求:产生一个集合里面都是整数
public List<Integer> getNumList(int num, Supplier<Integer> sup){
List<Integer> list = new ArrayList<>();
for (int i=0; i<num; i++){
list.add(sup.get());
}
return list;
}
//Function<T, R>:函数型接口
@Test
public void test3(){
String s1 = strHandle("\t\t\t 你好,中国! ", s -> s.trim());
System.out.println(s1);
String s2 = strHandle("abcdf", s -> s.toUpperCase());
System.out.println(s2);
}
//需求:用于处理字符串
public String strHandle(String str, Function<String, String> fun){
return fun.apply(str);
}
//Predicate<T>:断言型接口
@Test
public void test4(){
List<String> list = Arrays.asList("hello","www","lambda","ok");
List<String> resList = filterStr(list, s -> s.length() > 3);
resList.forEach(System.out::println);
}
//取出满足条件的字符串
public List<String> filterStr(List<String> list, Predicate<String> pred){
List<String> strList = new ArrayList<>();
for(String str : list){
if (pred.test(str)){
strList.add(str);
}
}
/* list.forEach(x-> {
if (pred.test(x)){
strList.add(x);
}
});
*/
return strList;
}
}
四、Java8中的引用
1. 方法引用:
主要有三种语法格式:
对象::实例方法名
类::静态方法名
类::实例方法名
注意:
(1)Lambda 体中调用方法的参数列表与返回值类型,要与函数式接口中抽象方法的函数式列表和返回值类型保持一致!
(2)Lambda 参数列表中第一个参数是实例方法的调用者,而第二个参数是实例方法的参数时,可以使用 ClassName::method
2. 构造器引用
格式:ClassName::new
注意:需要调用的构造器的参数列表要与函数式接口中抽象方法参数列表保持一致!
3. 数组引用
格式:Type::new
public class TestMethodRef {
//对象::实例方法名
@Test
public void test1(){
PrintStream ps = System.out;
//Lambda表达式
Consumer<String> con = x -> ps.println(x);
PrintStream ps1 = System.out;
//对象名::实例方法名
Consumer<String> con1 = ps1::println;
Consumer<String> con2 = System.out::println;
con2.accept("abcd");
}
@Test
public void test2(){
Employe emp = new Employe("赵云", 20,8888.88);
//Lambda表达式
Supplier<String> sup = ()-> emp.getName();
String s = sup.get();
System.out.println(s);
//对象名::实例方法名
Supplier<Integer> sup2 = emp::getAge;
Integer s2 = sup2.get();
System.out.println(s2);
}
//类::静态方法名
@Test
public void test3(){
//Lambda表达式
Comparator<Integer> com = (x,y) -> Integer.compare(x,y);
int r = com.compare(10, 5);
System.out.println(r);
//类::静态方法名
Comparator<Integer> com2 = Integer::compare;
int r2 = com2.compare(5, 10);
System.out.println(r2);
}
//类::实例方法名
@Test
public void test4(){
//Lambda表达式
BiPredicate<String, String> bp = (x, y) -> x.equals(y);
//方法引用(规则:第一个参数是实例方法的调用者,第二个参数是实例方法的参数)
BiPredicate<String, String> bp2 = String::equals;
}
//构造器引用
@Test
public void test5(){
//Lambda 表达式
Supplier<Employe> sup = ()-> new Employe();
//构造器引用
Supplier<Employe> sup2 = Employe::new;
}
//数组引用
@Test
public void test6(){
//Lambda 表达式
Function<Integer, String[]> fun = (x)-> new String[x];
String[] strs = fun.apply(10);
System.out.println(strs.length);
//数组引用
Function<Integer, String[]> fun2 = String[]::new;
String[] strs2 = fun.apply(8);
System.out.println(strs2.length);
}
}
【提示】可以理解把引用理解为 Lambda 表达式的另外一种表现形式