Lambda表达式
面向对象编程是对数据的抽象,面向函数编程是对行为的抽象。
Lambad表达式是一个匿名函数,可以说是接口或者抽象类的一种实现。
使用场景:
-
使用了@Functional 注释的函数式接口
-
自带一个抽象函数的方法
-
SAM(Single Abstract Method 单个抽象方法)类型
这些称为lambda表达式的目标类型,可以用作返回类型,或lambda目标代码的参数。例如,若一个方法接收Runnable、Comparable或者 Callable 接口,都有单个抽象方法,可以传入lambda表达式。
Lambda表达式使用
lambda表达式的本质: 作为函数式接口的实例
举例: (o1,o2) -> {
Integer.compare(o1,o2);
};
格式:
-> : lambda操作符
->左边 : lambda形参列表 (其实就是接口中的抽象方法的形参列表)
->右边 : lambda体 (其实就是重写的抽象方法体)
// 无参数,无返回
@Test
public void noArgument() {
Runnable r1 = new Runnable() {
@Override
public void run() {
System.out.println("匿名接口实现");
}
};
r1.run();
Runnable r2 = () -> System.out.println("lambda实现");
// 由此看出,lambda表达式的本质就是接口的实例
r2.run();
}
匿名接口实现
lambda实现
lambda表达式特征:
-
可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
-
可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
-
可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
-
可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定表达式返回了一个数值。
函数式接口
只包含一个抽象方法的接口,称为函数式接口。
可以通过Lambda表达式来创建该接口的对象。
定义: 使用@FunctionalInterface注解
Stream API
Stream 是Java8中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。
使用Stream API对集合进行操作,就类似于使用SQL执行的数据库查询。简单来说,Stream API提供了一种高效的处理数据的方式。
Stream是什么
stream是数据渠道,用于操作数据源(集合、数组)等所生成的元素序列。
与Collention的区别 : “集合讲的是数据,Stream讲的是计算“。
Stream执行流程
Stream的实例化
List<String> list = Arrays.asList("aaa", "bbb", "cccc");
// stream() : 顺序流
Stream<String> stream = list.stream();
// parallelStream() : 并行流
Stream<String> parallelStream = list.parallelStream();
一系列的中间操作
筛选和切片
// filter(Predicate p) --- Predicate断言 接收Lambda表达式,从流中排除某些元素
users.stream().filter(user -> user.getAge()>25).forEach(System.out::println);
System.out.println();
// limit(n) 截断流 ----只取n条数据
users.stream().limit(3).forEach(System.out::println);
System.out.println();
// skip(n) 跳过流 ----不要前n条数据
users.stream().skip(3).forEach(System.out::println);
System.out.println();
// skip(n) 跳过流 ----不要前n条数据
users.stream().skip(3).forEach(System.out::println);
System.out.println();
// distinct 去重 ----
users.stream().distinct().forEach(System.out::println);
System.out.println();
映射 Stream的map方法可以将集合中的每个对象转化为其他对象。
可以理解为将每个对象都进行处理、转换。
List<Student> list = new ArrayList<>();
Student stu1 = new Student("张三", 24);
Student stu2 = new Student("李四", 22);
Student stu3 = new Student("王五", 25);
Collections.addAll(list, stu1, stu2, stu3);
List<Teacher> teacList = list.stream().map(stu -> {
String name = stu.getName();
int age = stu.getAge();
return new Teacher(name, age);
}).collect(Collectors.toList());
teacList.stream().forEach(teacher -> System.out.println(teacher));
//Teacher{name='张三', age=24}
//Teacher{name='李四', age=22}
//Teacher{name='王五', age=25}
排序
// sorted() ---自然排序
List<Integer> list = Arrays.asList(23, 12, 455, 32, 4, 20);
list.stream().sorted().forEach(l -> System.out.println(l));
// sorted(Comparator com) ---定制排序
List<User> users = UserData.getUsers();
users.stream().sorted((u1,u2) -> {
int compare = Double.compare(u1.getSalary(), u2.getSalary());
if (compare !=0) {
return compare;
}else {
return Integer.compare(u1.getId(), u2.getId());
}
}).forEach(System.out::println);
终止操作
1-匹配与查找
List<User> users = UserData.getUsers();
// allMatch(Predicate p) - 检查是否匹配所有元素。 ---是否所有的员工的年龄都大于18
boolean match = users.stream().allMatch(user -> user.getAge() > 18);
System.out.println(match);
// anyMatch(Predicate p) - 检查是否至少匹配一个元素。 ---是否存在员工的工资大于10000
boolean b = users.stream().allMatch(user -> user.getSalary() > 10000);
System.out.println(b);
// noneMatch(Predicate p) - 检查是否没有匹配的元素。(没有返回true,有返回false) --是否存在员工姓"雷"
boolean noneMatch = users.stream().allMatch(user -> user.getName().startsWith("雷"));
System.out.println(noneMatch);
// findFirst - 返回第一个元素
Optional<User> first = users.stream().findFirst();
System.out.println(first.get());
// findAny - 返回当前流中的任意元素
Optional<User> any = users.stream().findAny();
System.out.println(any.get());
// count - 返回流中元素的总个数
long count = users.stream().filter(user -> user.getSalary() > 5000).count();
System.out.println(count);
// max(Comparator c) - 返回流中最大值 ---------返回最高的工资:
Stream<Double> salaryStream = users.stream().map(e -> e.getSalary());
Optional<Double> maxSalary = salaryStream.max(Double::compare);
System.out.println(maxSalary);
// min(Comparator c) - 返回流中最小值 ---------返回最低工资的员工
Optional<User> user = users.stream().min((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
// Optional[User(id=1005, name=陈几十块, age=30, salary=90.5)]
System.out.println(user);
// forEach(Consumer c) - 内部迭代
users.stream().forEach(System.out::println);
2-归约 reduce 相加
// reduce(T identity,BinaryOperator) - 可以将流中元素反复结合起来,得到一个值。返回 T
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Integer sum = list.stream().reduce(0, Integer::sum);
// 55
System.out.println(sum);
// reduce(BinaryOperator) - 可以将流中元素反复结合起来,得到一个值。返回 Optional<T> ----计算公司所有员工工资的总和
List<User> users = UserData.getUsers();
Optional<Double> reduce = users.stream().map(user -> user.getSalary()).reduce((s1, s2) -> s1 + s2);
System.out.println(reduce.get()); // 36893.8
3-收集 collect(Collector c) 将流转换为集合
List<User> users = UserData.getUsers();
// collect(Collector c):将流转换为其他形式。接收一个 Collector 接口的实现,用于给 Stream 中元素做汇总的方法
// ----查找工资大于 6000 的员工,结果返回为一个 List 或者 set
List<User> userList = users.stream().filter(user -> user.getSalary() > 6000).collect(Collectors.toList());
userList.forEach(System.out::println);
Set<User> userSet = users.stream().filter(user -> user.getSalary() > 6000).collect(Collectors.toSet());
userSet.forEach(System.out::println);
Optional类
这是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。
简单来说,这个类提供了一种判空的方式。
两个主要的方法:
isPresent: 如果值存在返回true,否则返回false。
get: 如果Optional有值则将其返回,否则抛出NoSuchElementException。
// findFirst - 返回第一个元素
Optional<User> first = users.stream().findFirst();
if (!first.isPresent()){
return;
}else {
first.get().setAge(111);
}
System.out.println(first.get());