一、简介
Lambda表达式是Java SE 8中一个重要的新特性。lambda表达式允许你通过表达式来代替功能接口。 lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体(body,可以是一个表达式或一个代码块)。
虽然看着很先进,其实Lambda表达式的本质只是一个"语法糖",由编译器推断并帮你转换包装为常规的代码,因此你可以使用更少的代码来实现同样的功能。
知识点:什么是语法糖?
语法糖(Syntactic sugar),是由Peter J. Landin(和图灵一样的天才人物,是他最先发现了Lambda演算,由此而创立了函数式编程)创造的一个词语,它意指那些没有给计算机语言添加新功能,而只是对人类来说更“甜蜜”的语法。
语法糖往往给程序员提供了更实用的编码方式,有益于更好的编码风格,更易读。不过其并没有给语言添加什么新东西。
需要声明的是“语法糖”这个词绝非贬义词,它可以给我带来方便,是一种便捷的写法,编译器会帮我们做转换;
而且可以提高开发编码的效率,在性能上也不会带来损失。
Lambda表达式还增强了集合库。 Java SE 8添加了2个对集合数据进行批量操作的包: java.util.function 包以及java.util.stream 包。 流(stream)就如同迭代器(iterator),但附加了许多额外的功能。 总的来说,lambda表达式和 stream 是自Java语言添加泛型(Generics)和注解(annotation)以来最大的变化。
Lambda表达式基本语法
(parameters)-> expression 或 (parameters)-> {statements}
举例如下:
// 1. 不需要参数,返回值为 5
() -> 5
// 2. 接收一个参数(数字类型),返回其2倍的值
x -> 2 * x
// 3. 接受2个参数(数字),并返回他们的差值
(x, y) -> x – y
// 4. 接收2个int型整数,返回他们的和
(int x, int y) -> x + y
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
(String s) -> System.out.print(s)
二、操作
1、使用lambda表达式进行集合遍历
//使用lambda表达式遍历
public static void traverse() {
String[] atp = {"Rafael Nadal", "Novak Djokovic",
"Stanislas Wawrinka",
"David Ferrer","Roger Federer",
"Andy Murray","Tomas Berdych",
"Juan Martin Del Potro"};
List<String> players = Arrays.asList(atp);
players.forEach((player) -> System.out.println(player+"; "));
}
2、lambda表达式操作对象
Person类(属性:firstName, lastName, job, gender, age, salary)
数据准备:
public static List<Person> generateJavaProgrammer() {
List<Person> javaProgrammers = new ArrayList<Person>() {
{
add(new Person("Elsdon", "Jaycob", "Java programmer", "male", 43, 2000));
add(new Person("Tamsen", "Brittany", "Java programmer", "female", 23,1500));
add(new Person("Floyd", "Donny", "Java programmer", "male", 33, 1800));
add(new Person("Sindy", "Jonie", "Java programmer", "female", 32, 1600));
add(new Person("Vere", "Hervey", "Java programmer", "male", 22, 1200));
add(new Person("Maude", "Jaimie", "Java programmer", "female", 27, 1900));
add(new Person("Shawn", "Randall", "Java programmer", "male", 30, 2300));
add(new Person("Jayden", "Corrina", "Java programmer", "female", 35,1700));
add(new Person("Palmer", "Dene", "Java programmer", "male", 33, 2000));
add(new Person("Addison", "Pam", "Java programmer", "female", 34, 1300));
}
};
return javaProgrammers;
}
public static List<Person> generatePhpProgrammer() {
List<Person> phpProgrammers = new ArrayList<Person>() {
{
add(new Person("Jarrod", "Pace", "PHP programmer", "male", 34, 1550));
add(new Person("Clarette", "Cicely", "PHP programmer", "female", 23, 1200));
add(new Person("Victor", "Channing", "PHP programmer", "male", 32, 1600));
add(new Person("Tori", "Sheryl", "PHP programmer", "female", 21, 1000));
add(new Person("Osborne", "Shad", "PHP programmer", "male", 32, 1100));
add(new Person("Rosalind", "Layla", "PHP programmer", "female", 25, 1300));
add(new Person("Fraser", "Hewie", "PHP programmer", "male", 36, 1100));
add(new Person("Quinn", "Tamara", "PHP programmer", "female", 21, 1000));
add(new Person("Alvin", "Lance", "PHP programmer", "male", 38, 1600));
add(new Person("Evonne", "Shari", "PHP programmer", "female", 40, 1800));
}
};
return phpProgrammers;
}
①forEach方法迭代输出所有程序员姓名
private static void traverseAllProgrammersName(List<Person> javaProgrammers, List<Person> phpProgrammers) {
System.out.println("forEach方法迭代输出所有程序员姓名:");
javaProgrammers.forEach((p) -> System.out.printf("%s %s;",p.getFirstName(),p.getLastName()));
phpProgrammers.forEach((p)-> System.out.printf("%s %s;", p.getFirstName(),p.getLastName()));
}
②forEach方法給Java程序員工资涨10%
private static void raiseMoney(List<Person> javaProgrammers) {
Consumer<Person> giveRaise = e -> e.setSalary(e.getSalary() / 100 * 10 +e.getSalary());
javaProgrammers.forEach(e -> System.out.printf("%d",e.getSalary()));
System.out.print("\n涨工资\n\t未加工资:\t");
javaProgrammers.forEach(e -> System.out.printf("%s %s:¥%d;",e.getFirstName(),e.getLastName(),e.getSalary()));
//涨工资
javaProgrammers.forEach(giveRaise);
System.out.print("\n\t输出加完工资后结果:\n\t");
javaProgrammers.forEach(e -> System.out.printf("%s %s:¥%d;",e.getFirstName(),e.getLastName(),e.getSalary()));
}
③lambda表达式结合stream之filter的使用:筛选月薪超过1500元的PHP程序员
什么是Stream?
Stream是对集合的包装,通常和lambda一起使用。 使用lambdas可以支持许多操作,如 map, filter, limit, sorted, count, min, max, sum, collect 等等。
private static void filterPhpProgrammer(List<Person> phpProgrammers) {
System.out.print("\n月薪超过1500元的PHP程序员:\n\t");
phpProgrammers.stream()
.filter(p -> p.getSalary() > 1400)
.forEach(p -> System.out.printf("%s %s:¥%d;",p.getFirstName(),
p.getLastName(),p.getSalary()));
}
④自定义过滤器:筛选年龄大于25岁且月薪在¥1500以上的女php程序员
private static void selfDefineFilter(List<Person> phpProgrammers) {
System.out.print("\n自定义过滤器筛选php程序员:\n\t");
//自定义过滤器
Predicate<Person> ageFilter = p -> p.getAge() > 25;
Predicate<Person> salaryFilter = p -> p.getSalary() > 1500;
Predicate<Person> genderFilter = p -> "female".equals(p.getGender());
System.out.print("年龄大于25岁且月薪在¥1500以上的女php程序员:\n\t");
phpProgrammers.stream().filter(ageFilter)
.filter(genderFilter)
.filter(salaryFilter)
.forEach(p -> System.out.printf("%s %s:¥%d;",p.getFirstName(),
p.getLastName(),p.getSalary()));
//自定义过滤器的好处就是可以重用
}
⑤limit方法的使用:筛选前4个php程序员
private static void limitPhpProgrammer(List<Person> phpProgrammers) {
System.out.println("\n筛选前4个php程序员:");
phpProgrammers.stream()
.limit(4)
.forEach(p -> System.out.printf("%s %s;",p.getFirstName(),
p.getLastName()));
//可以配合filter进行进一步筛选
}
⑥coloect方法的使用:先根据name排序再根据salary排序
private static void streamSortJavaProgrammer(List<Person> javaProgrammers) {
System.out.print("\nstream排序:\n\t根据name排序并只显示前5个javaProgrammer:\n\t");
List<Person> sortedJavaProgrammers = javaProgrammers.stream()
.sorted((p1,p2) -> p1.getFirstName().compareTo(p2.getFirstName()))
.limit(5)
.collect(Collectors.toList());
//输出结果
sortedJavaProgrammers.forEach(p -> System.out.printf("%s %s;",p.getFirstName(),
p.getLastName()));
System.out.print("\n\t再根据 salary 排序 javaProgrammer:\n\t");
sortedJavaProgrammers = sortedJavaProgrammers.stream()
.sorted((p1,p2) -> p2.getSalary() - p1.getSalary())
.collect(Collectors.toList());
sortedJavaProgrammers.forEach(p -> System.out.printf("%s %s:¥%d;",p.getFirstName(),
p.getLastName(),p.getSalary()));
}
⑦max、min的用法:获得Java程序员中工资最高和最低者的信息
private static void getExtreValue(List<Person> javaProgrammers) {
System.out.print("\n获得最值:\n\t工资最低的javaProgrammer:\n\t");
Person minSalaryPm = javaProgrammers.stream().min((p1,p2) -> p1.getSalary() - p2.getSalary()).get();
System.out.print(minSalaryPm.getFirstName()+" "+minSalaryPm.getLastName()+":¥"+minSalaryPm.getSalary());
System.out.print("\n\t工资最高的javaProgrammer:\n\t");
Person maxSalaryPm = javaProgrammers.stream().max((p1,p2) -> p1.getSalary() - p2.getSalary()).get();
System.out.println(maxSalaryPm.getFirstName()+" "+maxSalaryPm.getLastName()+":¥"+maxSalaryPm.getSalary());
}
注:此处工资与元数据多了10%是因为前raiseSalary操作所致。
三、总结
通过学习初步掌握了lambda表达式的使用,lambda表达式让我们可以用更少的代码来实现相同的功能,因此lambda表达式可以使代码变得更加简洁紧凑,便捷的写法提高了开发编码的效率。
四、参考
http://www.runoob.com/java/java8-lambda-expressions.html
https://www.cnblogs.com/franson-2016/p/5593080.html
五、示例代码
链接:https://pan.baidu.com/s/1hBGFIxS5yf2CPnjZsunGMA 密码:r0fq