一,Lambda表达式的使用
1.举例:Comparator c= Comparator.comparingInt(o -> o);
2.格式:->:Lambda操作符
左边叫做形参列表,其实就是接口中的抽象方法的形参列表
右边叫做Lambda体(重写的抽象方法的方法体)
3.关于Lambda表达式的使用
总结:
-> 左边:lambda形参列表的参数类型可以省略(类型推断),如果形参列表只有一个参数,()可以省略。
-> 右边:Lambda体应该使用一对{}包裹,如果Lambda体只有一条执行语句(可能是return语句),{}和return也可以省略。
要求接口只有一个抽象方法。
4.Lambda表达式的本质:作为函数式接口的实例。
5.如果一个接口中只声明了一个抽象方法,则此接口称为函数式接口。
可以使用注解@FunctionalInterface检查是否是一个函数式接口。
用匿名实现类表示的现在都可以用Lambda表达式表示。
语法格式
/**
* @author yhd
* @createtime 2020/11/13 22:43
*/
public class DemoA {
//语法格式一:无参数,无返回值
@Test
public void test1() {
Runnable run = () -> System.out.println("语法格式一:无参数,无返回值");
run.run();
}
//语法格式二:一个参数,无返回值
@Test
public void test2() {
Consumer<String> consumer = args -> System.out.println(args);
consumer.accept("语法格式二:一个参数,无返回值");
}
//语法格式三:Lambda 需要两个以上参数,多条执行语句,并且有返回值。
@Test
public void test3() {
Comparator<Integer> comparable = (args1, args2) -> {
System.out.println("args1 = " + args1);
System.out.println("args2 = " + args2);
return args1 > args2 ? 1 : (args1 == args2 ? 0 : -1);
};
System.out.println("comparable.compare(1,2) = " + comparable.compare(1, 2));
}
}
二,方法引用
Java内置四大核心函数式接口(要求能看懂)
消费性接口 Consumer void accept(T t)
供给型接口 Supplier T get()
函数型接口 Function
断定型接口 Predicate boolean test(T t)
使用情景:当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用。
方法引用:本质上就是Lambda表达式,而Lambda表达式作为函数式接口的实例,
所以方法引用,也是函数式接口的实例。
使用格式: 类(对象)::方法名
具体分为如下三种情况:
对象::非静态方法
类::静态方法
类::非静态方法
方法引用的使用要求,要求接口中的抽象方法的形参列表和返回值类型与方法引用
的方法的形参列表和返回值类型相同!
语法格式
/**
* @author yhd
* @createtime 2020/11/13 22:43
*/
public class DemoA {
private static void run() {
System.out.println("语法格式一:无参数,无返回值");
}
private static int compare(Integer args1, Integer args2) {
System.out.println("args1 = " + args1);
System.out.println("args2 = " + args2);
return args1 > args2 ? 1 : (args1 == args2 ? 0 : -1);
}
//语法格式一:无参数,无返回值
@Test
public void test1() {
Runnable run = DemoA::run;
run.run();
}
//语法格式二:一个参数,无返回值
@Test
public void test2() {
Consumer<String> consumer = System.out::println;
consumer.accept("语法格式二:一个参数,无返回值");
}
//语法格式三:Lambda 需要两个以上参数,多条执行语句,并且有返回值。
@Test
public void test3() {
Comparator<Integer> comparable = DemoA::compare;
System.out.println("comparable.compare(1,2) = " + comparable.compare(1, 2));
}
//语法格式四:
@Test
public void test4(){
Comparator<Integer>comparator= Integer::compareTo;
System.out.println("comparator.compare(1,2) = " + comparator.compare(1, 2));
}
}
三,构造器引用
和方法引用类似,函数式接口的抽象方法的形参列表和构造器的形参列表一致,抽象方法的返回值类型就是构造器所属的类的类型。
数组引用
大家可以把数组看作一个特殊的类,则写法与构造器引用一致。
语法格式
/**
* @author yhd
* @createtime 2020/11/14 0:18
*/
public class DemoB {
@Test
public void test1(){
BiFunction<String,String,Employee> emp = Employee::new;
Employee employee = emp.apply("AA", "20");
System.out.println("employee = " + employee);
}
@Test
public void test2(){
Supplier<Employee> emp = Employee::new;
Employee employee = emp.get();
System.out.println("employee.toString() = " + employee.toString());
}
@Test
public void test3(){
Function<Integer,Integer[]> params = Integer[]::new;
Integer[] arrs = params.apply(5);
System.out.println(Arrays.toString(arrs));
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
class Employee{
private String name;
private String age;
}
四,Stream
1.Stream关注的是数据的运算,与CPU打交道。
集合关注的是是数据的存储,与内存打交道。
2.
①Stream自己不会存储元素。
②Stream不会改变源对象,相反,他们会返回一个持有结果的新Stream。
③Stream操作是延迟执行的,这意味着它们会等到需要结果的时候才执行。
3.Stream的执行流程
①Stream的实例化
②一系列的中间操作(过滤,映射,。。。)
③终止操作
4.说明:
①一个中间链操作,对数据源的数据进行处理。
②一旦执行终止操作,就执行中间操作链,并产生结果。之后,不会再被使用。
1.实例化
/**
* @author yhd
* @createtime 2020/11/14 20:18
*/
public class DemoC {
/**
* 流的4种实例化方式一:
* 通过集合
* 顺序流和并行流的区别:
* 顺序流按照集合的顺序挨个取出元素
* 并行流开多个线程去取,取出元素的顺序可能会发生变化
*/
@Test
public void test1(){
List<Integer> list=new ArrayList<>();
//创建一个顺序流
Stream<Integer> stream = list.stream();
//创建一个并行流
Stream<Integer> parallelStream = list.parallelStream();
}
/**
* 流的4种实例化方式二:
* 通过数组
*
*/
@Test
public void test2(){
Integer []a=new Integer[]{1,2,3,4,5,6};
Stream<Integer> stream = Arrays.stream(a);
}
/**
* 流的4种实例化方式三:
* 通过of
*/
@Test
public void test3(){
Stream<Integer> stream = Stream.of(1, 2, 3);
}
/**
* 流的4种实例化方式四:
* 无限流
*/
@Test
public void test4(){
//迭代
Stream.iterate(0,t->t+2).limit(10).forEach(System.out::print);
//生成
Stream.generate(Math::random).limit(10).forEach(System.out::print);
}
}
2,中间操作
1.过滤
/**
* @author yhd
* @createtime 2020/11/14 21:20
*/
public class Demo4 {
private static List<Person> persons = new ArrayList<>();
private static Stream<Person> stream;
static {
persons.add(new Person("1","马云",200.00));
persons.add(new Person("2","马化腾",200.00));
persons.add(new Person("3","李彦宏",200.00));
persons.add(new Person("4","刘强东",200.00));
persons.add(new Person("5","张朝阳",200.00));
persons.add(new Person("5","张朝阳",200.00));
stream = persons.stream();
}
//limit()截断取前面
@Test
public void test1() {
stream.limit(2).forEach(System.out::println);
}
//filter()过滤出需要的元素
@Test
public void test2(){
stream.filter(Demo4::test).forEach(System.out::println);
}
private static boolean test(Person person) {
return person.getSalary() > 7000;
}
//skip()截断取后面
@Test
public void test3(){
stream.skip(2).forEach(System.out::println);
}
//distinct()去除重复元素
@Test
public void test4(){
stream.distinct().forEach(System.out::println);
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
class Person implements Serializable {
private String id;
private String name;
private Double salary;
}
2.映射
/**
* @author yhd
* @createtime 2020/11/14 22:04
*/
public class DemoD {
private static List<Person> persons = new ArrayList<>();
private static Stream<Person> stream;
static {
persons.add(new Person("1", "马云", 200.00));
persons.add(new Person("2", "马化腾", 200.00));
persons.add(new Person("3", "李彦宏", 200.00));
persons.add(new Person("4", "刘强东", 200.00));
persons.add(new Person("5", "张朝阳", 200.00));
stream = persons.stream();
}
/**
* map和flatMap的区别:
* list.add(list);
* list.addAll(list);
*/
@Test
public void test1() {
stream.map(Person::getName).filter(e -> e.length() > 2).forEach(System.out::println);
}
@Test
public void test2() {
Arrays.asList("aa", "bb", "cc").stream().map(DemoD::StringToStream).forEach(DemoD::accept);
Arrays.asList("aa", "bb", "cc").stream().flatMap(DemoD::StringToStream).forEach(System.out::println);
}
private static void accept(Stream<Character> e) {
e.forEach(System.out::println);
}
public static Stream<Character> StringToStream(String str) {
List<Character> result = new ArrayList<>();
for (Character s : str.toCharArray())
result.add(s);
return result.stream();
}
}
3.排序
/**
* @author yhd
* @createtime 2020/11/14 22:41
*/
public class DemoE {
private static List<Person> persons = new ArrayList<>();
private static Stream<Person> stream;
static {
persons.add(new Person("1", "马云", 200.00));
persons.add(new Person("2", "马化腾", 200.00));
persons.add(new Person("3", "李彦宏", 200.00));
persons.add(new Person("4", "刘强东", 200.00));
persons.add(new Person("5", "张朝阳", 200.00));
persons.add(new Person("5", "张朝阳", 200.00));
stream = persons.stream();
}
@Test
public void test1() {
stream.sorted(DemoE::compare);
}
private static int compare(Person o1, Person o2) {
return o1.getSalary() > o2.getSalary() ? 1 : (o1.getSalary() == o2.getSalary() ? 0 : -1);
}
}
3,终止操作
1.匹配与查找
/**
* @author yhd
* @createtime 2020/11/14 22:48
* 终止操作:匹配与查找
*/
public class DemoF {
private static List<Person> persons = new ArrayList<>();
private static Stream<Person> stream;
static {
persons.add(new Person("1", "马云", 200.00));
persons.add(new Person("2", "马化腾", 200.00));
persons.add(new Person("3", "李彦宏", 200.00));
persons.add(new Person("4", "刘强东", 200.00));
persons.add(new Person("5", "张朝阳", 200.00));
persons.add(new Person("5", "张朝阳", 200.00));
stream = persons.stream();
}
//全部匹配返回true
@Test
public void test1() {
System.out.println(stream.allMatch(p -> p.getSalary() > 100));
}
//任意匹配返回true
@Test
public void test2() {
System.out.println(stream.anyMatch(p -> p.getSalary() > 100));
}
//都不匹配返回true
@Test
public void test3() {
System.out.println(stream.noneMatch(p -> p.getSalary() > 300));
}
//获取流里面第一个
@Test
public void test4() {
System.out.println(stream.findFirst().get());
}
//获取流里面随机一个
@Test
public void test5() {
System.out.println(stream.findAny());
}
//获取流里面元素个数
@Test
public void test6() {
System.out.println(stream.count());
}
//获取最大
@Test
public void test7() {
System.out.println(stream.max(Comparator.comparing(Person::getSalary)).get());
}
//获取最小
@Test
public void test8() {
System.out.println(stream.min(Comparator.comparing(Person::getSalary)).get());
}
}
2.归约
public class DemoF {
private static List<Person> persons = new ArrayList<>();
private static Stream<Person> stream;
static {
persons.add(new Person("1", "马云", 200.00));
persons.add(new Person("2", "马化腾", 200.00));
persons.add(new Person("3", "李彦宏", 200.00));
persons.add(new Person("4", "刘强东", 200.00));
persons.add(new Person("5", "张朝阳", 200.00));
persons.add(new Person("5", "张朝阳", 200.00));
stream = persons.stream();
}
@Test
public void test9(){
System.out.println(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9).stream().reduce(10, Integer::sum));
}
@Test
public void test10(){
System.out.println(stream.map(Person::getSalary).reduce(0.0, Double::sum));
}
}
3.收集
collect(Collector())
Collector 接口中方法的实现决定了如何对流执行收集的操作。
Collectors实用类提供了很多静态方法,可以方便的创建常见的收集器实例。
/**
* @author yhd
* @createtime 2020/11/14 22:48
*
*/
public class DemoF {
private static List<Person> persons = new ArrayList<>();
private static Stream<Person> stream;
static {
persons.add(new Person("1", "马云", 200.00));
persons.add(new Person("2", "马化腾", 200.00));
persons.add(new Person("3", "李彦宏", 200.00));
persons.add(new Person("4", "刘强东", 200.00));
persons.add(new Person("5", "张朝阳", 200.00));
persons.add(new Person("5", "张朝阳", 200.00));
stream = persons.stream();
}
//列出员工的所有工资
@Test
public void test1(){
stream.map(Person::getSalary).collect(Collectors.toList()).forEach(System.out::println);
}
//列出每个员工的工资
@Test
public void test2(){
//System.out.println(stream.distinct().collect(Collectors.toMap(Person::getName, person -> person)));
System.out.println(stream.distinct().collect(Collectors.toMap(Person::getName, Person::getSalary)));
}
}
五,Optional
Optional提供了很多有用的方法,这样我们就不用显示的进行空值检测。
1.创建Optional类对象的方法:
Optional.of(T t):创建一个Optional实例,t必须非空。
Optional.empty():创建一个空的Optional实例。
Optional.ofNullable(T t):t可以为null。
2.判断Optional容器中是否包含对象:
boolean isPresent() 判断是否包含对象
void ifPresent(Consumer<? super T> consumer):如果有值,就执行Consumer接口的实现代码,并且该值作为参数传给他。
3.获取Optional容器的对象
T get() 如果调用对象包含值,返回该值,否则抛出异常
T orElse(T other) 如果有值则将其返回,否则返回指定的other对象
T orElseGet(Supperlier<? super T> other) 如果有值则将其返回,否则返回由Supplier接口实现提供的对象。
T orElseThrow(Supperlier<? super X> exceptionSupplier) 如果有值则将其返回,否则抛出由Supplier接口实现提供的异常。
/**
* @author yhd
* @createtime 2020/11/15 0:44
*/
public class DemoG {
@Test
public void test() {
Girl girl = new Girl();
System.out.println(Optional.ofNullable(Optional.ofNullable(girl).orElseGet(Girl::new).getBoy()).orElseGet(Boy::new).getName());
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
class Girl {
private Boy boy;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
class Boy {
private String name;
}