Function function = () -> System.out.println("我来自Lambda表达式");
function.run();
显然,在这里出现了一段奇怪的代码:
() -> System.out.println()
这便是Lambda表达式,其本质作用便是 简化代码
让我们来看看它的简化历程:
//定义一个声明了需要显示颜色的接口
public interface Fruit{
public void showColor();
}
//创建一个接口的实现类
public class Apple implements Fruit {
//重写showColor方法
@Override
public void showColor() {
System.out.println("苹果是红色的");
}
}
传统实现声明式接口 的编码过程。
以上代码可以采用 匿名内部类 的方法将其简化:
public class Test {
public static void main(String[] args) {
Fruit fruit = new Fruit() {
@Override
public void showColor() {
System.out.println("苹果是红色的");
}
}; //到此处才为完整的一句
fruit.showColor;
}
}
即在实例化接口的时候将函数重写
不过,虽然我们省去了新建一个实现类的过程,但是这么多行代码下来,所要达到的目的不过是一句
System.out.println("苹果是红色的");
所以,Lambda表达式便出现了:
public class Test {
public static void main(String[] args) {
Fruit fruit = () -> System.out.println("苹果是红色的");
fruit.showColor();
}
}
没错,就只剩下这一句,它的意思是这样的:
i. “()” :该方法的 参数列表,即showColor后边的 “()”;
ii. “->”: 方法体为:
iii. “sout”:方法体
总结一下:
实现类 简化为 静态内部类 简化为 Lambda表达式
Lambda的出现极大程度上减少了代码的冗余
//首先我们创建一个打印接口
public interface Print {
public void print(String s);
}
//创建一个测试类并引用System类下的println方法
public class Test {
public static void main(String[] args) {
Print p = System.out::println;
p.print("我是print方法引用println方法打印出来的");
}
}
i. 接口中的抽象方法需要被实现
ii. 接口中的抽象方法的参数列表、返回值类型与某一个已实现的方法完全相同(抽象方法print和System.out.println方法)
此时便可以通过 引用此方法来达到实现接口的目的
在流式编程中,以往需要操作数组、集合时的数十行代码,只需要一两行即可实现,即:
i. 大幅降低代码的复杂度和出错率,效率提升
ii. 包含大量Lambda表达式和方法引用,较为抽象
iii. 需要明白函数式接口的概念
//创建一个字符串类集合
public class Test {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("大家好");
list.add("我是");
list.add("传统编程");
//传统foreach打印
for (String s : list) {
System.out.println(s);
}
}
}
public class Test {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("大家好");
list.add("我是");
list.add("流式编程");
list.stream().forEach(System.out::println);
}
}
以上便是流式编程的操作过程,``只需要一行代码即可完成所需要的操作,并且不用关心其实现过程。
以下是流式编程的方法详细使用的过程:
//创建一个对象类
public class Object1 {
private String name;
private int age;
private String address;
public Object1(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
@Override
public String toString() {
return name + " : " + age + " : " + address;
}
public class Test {
public static void main(String[] args) {
List<Object1> list = new ArrayList<>();
list.add(new Object1("萧炎", 20,"萧家"));
list.add(new Object1("古薰儿", 19,"古族"));
list.add(new Object1("彩鳞", 30,"蛇人族"));
list.add(new Object1("云韵", 27,"云岚宗"));
list.add(new Object1("云韵", 27,"云岚宗"));
//打印所有信息
list.stream().forEach(System.out::println);
list.stream().forEach(x -> System.out.println(x));
//打印年龄大于23的人物信息
list.stream().filter(x -> x.getAge() > 23).forEach(System.out::println);
//重写equals方法达到可引用的目的
list.stream().filter(new Object1() ::equals).forEach(System.out::println);
// //过滤第一个大于23岁且打印
list.stream().filter(x -> x.getAge() > 23).limit(1).forEach(System.out::println);
//
// //skip跳过前几个
list.stream().filter(x -> x.getAge() > 23).skip(1).limit(1).forEach(System.out::println);
//打印所有对象的名字
list.stream().map(x -> x.getName()).forEach(System.out::println);
//distinct去重
list.stream().distinct().forEach(System.out::println);
//allmatch是否都匹配
System.out.println(list.stream().allMatch(x -> x.getAge() <= 30));
//拿到第一个年龄大于23的
Optional<Object1> first = list.stream().filter(x -> x.getAge() > 23).findFirst();
System.out.println(first.get());
//打印名字为两位长度的个数
System.out.println(list.stream().filter(x -> x.getName().length() == 2).count());
//所有人年龄和
System.out.println(list.stream().mapToInt(x -> x.getAge()).sum());
// 求名字长度为2的年龄最大者
// max:返回Int,负值小于,0等于,正值大于
Optional<Object1> max = list.stream().filter(x -> x.getName().length() == 2).max((x, y) -> y.getAge() - x.getAge());
System.out.println(max.get());
//sorted排序
list.stream().sorted((x, y) -> y.getAge() - x.getAge()).forEach(System.out::println);
}
}