Lambda基础语法
语法格式1:无参数,无返回值
() -> System.out.println("Hello Lambda!");
语法格式2: 有一个参数,无返回值
(x) -> System.out.println(x);
语法格式3:只有一个参数,小括号可以不写
x -> System.out.println(x);
语法格式4:有两个以上参数,有返回值,并且Lambda体中有多条语句
Comparator<Integer> com = (x,y) -> {
System.out.println("Hello Lambda");
return Integer.compare(x,y);
};
语法格式5:若Lambda体重只有一条语句,return和大括号可以神略不写
Comparator<Integer> com = (x,y) -> Integer.compare(x,y);
语法格式6:Lambda 表达式的参数列表的数据类型可以省略不写,因为JVM编译器通过上下文推断出数据类型,即“类型推断”
(Integer x,Integer y) -> Integer.compare(x,y);
小结:
上联:左右遇一括号省
下联:左侧推断类型省
横批:能省则省
Lambda表达式需要“函数式接口”的支持
函数式接口:接口中只有一个抽象方法的接口,称为函数式接口。可以使用注解@FunctionalInterface修饰来判断是否为函数式接口
Java8 内置的四大核心函数式接口
- Consumer :消费型接口
void accept(T t)
Consumer<Double> consumer= (x) -> System.out.println("今天消费了" + x + "元");
consumer.accept(100.0);
- Supplier:供给型接口
T get();
Supplier<Integer> supplier = () -> (int) (Math.random() * 100);
System.out.println(supplier.get());
- Function<T,R>:函数型接口
R apply(T t)
Function<String, String> fucFunction = (str) -> str.trim();
String str = "\t\t\t 你好啊Lambda ";
System.out.println("原来的字符串:" + str);
String result = fucFunction.apply(str);
System.out.println("处理后的字符串:" +result);
- Predicate :断言型接口
boolean test(T t)
Predicate<String> predicate = (str) -> str.equals("aa");
System.out.println(predicate.test("aa"));
System.out.println(predicate.test("bb"));
方法引用
若Lambda体中的内容有方法已经实现了,我们可以使用“方法引用”
(可以理解为方法引用是Lambda表达式的另一种表现是形式)
主要有三种语法格式:
对象 :: 实例方法名(不需要加括号)
类 :: 静态方法名(不需要加括号)
类 :: 实例方法名(不需要加括号)
注意:
1.Lambda提中调用方法的参数列表与返回值类型,要与函数式接口中的抽象方法的函数列表和返回值要保持一致
2.若Lambda参数列表中的第一个参数是实例方法的调用者,第二个参数是实例方法的参数,可以使用ClassName :: method
Employee emp = new Employee();
Supplier<String> sup = () -> emp.getName();
System.out.println(sup.get());
// 使用方法引用 -> 对象 :: 实例方法名(不需要加括号)
Supplier<String> sup2 = emp::getName;
System.out.println(sup2.get());
// 使用方法引用 -> 类 :: 静态方法名(不需要加括号)
Comparator<Integer> com = (x,y) -> Integer.compare(x,y);
Comparator<Integer> com1 = Integer::compare;
// 使用方法引用 -> 类 :: 实例方法名(不需要加括号)
BiPredicate<String ,String> bp = (x,y) -> x.equals(y);
BiPredicate<String ,String> bp2 = String :: equals;// 当第一个参数是方法的调用者,第二个参数时该方法的参数,则可以使用: 类 :: 实例方法名
构造器引用
- 格式:
ClassName :: new
Supplier<Employee> sup = () -> new Employee();
Supplier<Employee> sup1 = Employee::new;// 自动匹配Supplier的参数列表,这个接口有几个参数,就调用几个参数的构造器
数组引用
- 格式:
Type :: new;
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 = fun2.apply(20);
System.out.println(Strs2.length());
Stream(流)
-
是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列
-
(集合讲的是数据,流讲的是计算)
-
注意
Stream自己不会存储元素。 Stream不会改变源对象。相反,他们会返回一个持有结果的新Stream Stream操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。
Stream的操作三个步骤
-
创建Stream
一个数据源(如:集合、数组),获取一个流
-
中间操作
一个中间操作链,对数据源的数据进行处理 多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作哦,否则中间操作不会执行任何处理!而在终止操作时一次触发全部处理,称为:惰性求值
方法 | 描述 |
---|---|
filter(Predicate p) | 接收Lambda,从流中排除某些元素 |
distinct()筛选,通过流所生成元素的hasCode()和equals()去除重复元素 | |
limit(long maxSize) | 截断流,使其元素不超过给定数量 |
skip(long n) | 跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流。与limit(n)互补 |
-
终止操作(终端操作)
一个终止操作,执行中间操作链,并产生结果
public void test1(){
// 1.通过Collection系列集合提供的stream()或parallelStream()
List<String> list = new ArrayList<>();
Stream<String> stream1 = list.stream();
// 2.通过Arrays中的静态方法stream()获取数组流
Employee[] emps = new Employee[10];
Stream<Employee> stream2 = Arrays.stream(emps);
// 3.通过Stream类中的静态方法of()
Stream<String> stream3 = Stream.of("aa","bb","cc");
// 4.创建无限流
// 迭代
String<Integer> stream4 = Stream.iterate(0,(x) -> x + 2);
stream4.limit(10).forEach(System.out::prinltn);
// 生成
Stream.generate(() -> Math.random())
.limit(5)
.forEach(System.out::println);
}
public void test2(){
// 中间操作:不会执行任何操作,只有执行了终止操作才会执行
Stream<Employee> stream = employees.stream()
.filter((e) -> e.getAge() > 35);
stream.forEach(System.out::println);
}
// 内部迭代由stream API 完成
// 外部迭代
public void test3(){
Iterator<Employee> it = employee.iterator();
while(it.hasNext()){
System.out.println(it.next);
}
}
映射
- map - 接收Lambda,将元素转换成其他形式或提取信息,接收一个函数作为参数,该函数会被应用 到每个元素上,并将其映射成一个新的元素。
- flatMap - j接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
public void test5(){
List<String> list = Arrays.asList("aa","bb");
list.stream()
.map((str) -> str.toUpperCase())
.forEach(System.out::println);
employees.stream()
.map(Employee::getName)
.forEach(System.out::println);
}
Optional类
-
Optional 容器类常用的方法:
Optional.of(T t): 创建一个Optional实例 Optional.empty() : 创建一个空的Optional实例 Optional.ofNullable(T t) : 若t不为null,创建Optional实例,否则创建空实例 isPresent() : 判断是否包含值 orElse(T t) : 如果调用对象包含值,则返回该值,否则返回t orElseGet(Supplier s) : 如果调用对象包含值,则返回该值,否则返回s获取的值 map(Function f) : 如果有值对其处理,并返回处理后的Optional.empty() flatMap(Function mapper) : 与map类似,要求返回值必须是Optional