1Lambda 表达式
Lamdba 表达式是一种没有名字的函数,也可称为闭包,是JAVA 8 发布的中重要新特性
本质上上一段匿名内部类。也可以是一段可以传递的代码,还有叫箭头函数的
闭包:
闭包就是能够读取其他函数内部变量的函数,比如在java中 方法内部的局部变量 只能在方法内部使用,所以闭包可以理解为定义在一个函数内部的函数
闭包的本质就是将函数内部和函数外部链接起来的桥梁
1.2 lambda 特点
允许把函数作为一个方法的参数(函数作为参数传递进方法中)
使用Lambda 表达式可以使代码变得更加简洁紧凑
lambda 和匿名内部类对比
Integer[] arr = {1,2,5,3,8,45,3};
//asList: 把数组转换为List集合
List<Integer> integers = Arrays.asList(arr);
//匿名内部类写法
// Collections.sort(integers, new Comparator<Integer>(){
// public int compare(Integer o1,Integer o2){
// return o2-o1;
// }
// });
//lambda
Collections.sort(integers, (i1,i2) -> i2-i1);
System.out.println(integers);
}
1.3 lambd 应用场景
1)列表迭代 2)Map映射 3)Reduce 聚合 4)代替一个不想命名的函数或是类,该函数或类往往并不复杂 4)想尽量缩短代码量的各个场景均可以
1.4.1具体语法:
(parameters) -> expression
(parameters) ->{statements;}
1.4.2语法特点
可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。可选的大括号:如果主体包含了一个语句,就不需要使用大括号。可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值 如果只有一条语句,并且是返回值语句,就可以不写return 不写 {}
如果写上{} 就必须写return 和 ;
如果有 多条语句,必须写{} return 和 ; 也必须写
案例说明-简单
// 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)
2 函数式接口
2.1介绍
其本质是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。核心目标是为了给Lambda表达式的使用提供更好的支持,进一步达到函数式编程的目标,可通过运用函数式编程极大地提高编程效率。其可以被隐式转换为 lambda 表达式。
2.2特点:
函数式接口是仅制定一个抽象方法的接口
可以包含一个或多个静态或默认方
专用注解即@FunctionalInterface 检查它是否是一个函数式接口,也可不添加该注解
如果有两个或以上 抽象方法,就不能当成函数式接口去使用,也不能添加@FunctionalInterface这个注解
如果只有一个抽象方法,那么@FunctionalInterface注解 加不加 都可以当做函数式接口去使用
2.3代码实现
* Supplier 接口 有一个get方法 用于获取数据
public class FunInterface_01 {
public static int sum(Supplier<Integer>sup){
return sup.get();
}
public static void main(String[] args){
int result = sum(()->1+2);
System.out.println(result);
}
}
package FunInterface;
import java.util.function.Consumer;
public class FunInterface_02 {
public static void print(Consumer<String> con,String msg){
con.accept(msg);
}
public static void main(String[] args){
print((str) -> System.out.println(str), "你好吗");
}
}
3.1 方法引用
对象引用:: 成员方法
*要求: 使用接口的抽象方法的入参和出参,必须和调用方法的入参出参一致
public class FunCall_01 {
public static void main(String[] args){
Integer i1 = 10;
//方法调用
String str = i1.toString();
System.out.println(str);
//lambda 表达式写法
Supplier<String> su = ()->i1.toString();
System.out.println(su.get());
//方法引用写法
Supplier<String> su1 = i1::toString;
}
}
类名 ::静态方法名
public class FunCall_02 {
public static void main(String[] args){
int max = Integer.max(11,21);
BiFunction<Integer,Integer,Integer> bf = Integer::max;
System.out.println(bf.apply(11, 21));
}
}
类名:: 成员方法
public class FunCall_03 {
public static void main(String[] args){
BiPredicate<String,String> bp = String::equals;
System.out.println(bp.test("axz", "axz"));
}
}
创建对象
public class FunCall_04 {
public static void main(String[] args){
Object o1 = new Object();
Supplier<Object> sp = Object::new;
System.out.println(sp.get());
}
}
4 Stream API
4.1概念说明
数据渠道,管道,用于操作数据源(集合,数组等)所生成的元素序列
集合讲的是数据,流讲的是计算,即一组用来处理数组,集合的API
4.2
Stream 不是数据结构,没有内部存储,自己不会存储元素。
Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。
不支持索引访问。
延迟计算
支持并行
很容易生成数据或集合
支持过滤,查找,转换,汇总,聚合等操作
4.3 运行机制说明
Stream分为源source,中间操作,终止操作。
流的源可以是一个数组,集合,生成器方法,I/O通道等等。
一个流可以有零个或多个中间操作,每一个中间操作都会返回一个新的流,供下一个操作使用,一个流只会有一个终止操作。
中间操作也称为转换算子-transformation
Stream只有遇到终止操作,它的数据源会开始执行遍历操作。
终止操作也称为动作算子-action
因为动作算子的返回值不再是 stream,所以这个计算就终止了
只有碰到动作算子的时候,才会真正的计
4.4代码实现
public static void main(String[] args){
//1数组,通过stream 类的of 方法即可
String[] strings = {"a","b","c","d"};
Stream<String> stream1 = Stream.of(strings);
//2集合 通过集合对象的stream 方法即可
List<String> strings2 = Arrays.asList(strings);
Stream<String> stream2 = strings2.stream();
//3 通过Stream 的generate方法创建无限流
//该流无限大,建议使用limit 限制条数
//参数是一个Supplier 接口,有一个get方法,无参,有返回值
//返回的数据就会被放到这个无限流中,也就是目前这个流中的数据都是1
Stream<Integer> stream3 = Stream.generate(() ->1);
stream3.limit(8).forEach(x ->System.out.println(x));
//4 通过Stream.iterate 方法创建无限流
//第一个参数是起始值,第二个参数是UnaryOperator, 是 function 的子类,所以是有参返回值
// x-> x+2 : 等于步长为2, 那么此时,数据流中内容1,3,5.......
Stream<Integer> stream4 = Stream.iterate(1, x ->x+2);
stream4.limit(7).forEach(x-> System.out.println(x));
//5 已有类的streamAPI
String string = "sadas";
IntStream is = string.chars();
is.forEach(x ->System.out.println(x));
}
public static void main(String[] args){
List<String> strings = Arrays.asList("a","b","c","a","d");
/**
* filter: 对元素进行过滤,不符合条件的就不要了
*/
Stream<String> stream = strings.stream();
//collect: 收集器,把流转换为集合
// x-> !x.equals("a") 只要不是a的
List<String> result = stream.filter(x->!x.equals("a")).collect(Collectors.toList());
System.out.println(result);
//流一旦使用过,必须重新生成,否则报错,所以每个中间操作都是返回一个新的流,因为原来的流不能用了
/**
* distinct 去除重复
*/
stream = strings.stream();
result = stream.distinct().collect(Collectors.toList());
System.out.println(result);
/**
* map
*/
List<Integer> says = Arrays.asList(2000,1000,1500,7300,5000);
Stream<Integer> stream1 = says.stream();
//所有人张薪资百分之十
says = stream1.map(x-> x+x/100*10).collect(Collectors.toList());
System.out.println(says);
/**
* sorted 排序
*/
stream1 = says.stream();
//默认是升序
//says = stream1.sorted((x,y) ->x-y).collect(Collectors.toList());
//降序
says = stream1.sorted((x,y) ->y-x).collect(Collectors.toList());
System.out.println(says);
}
* 终止操作 又称为动作算子
* forEach 循环遍历
* collect 收集器
* 计算相关: min,max,count,avrage
* 匹配相关: anyMatch, allMatch....
*/
public class Stream_03 {
public static void main(String[] args){
List<String> strings = Arrays.asList("a","b","c","a");
//forEach
Stream<String> stream = strings.stream();
stream.forEach(x -> System.out.println(x));
//统计
stream = strings.stream();
//统计元素个数,一般需要和中间操作结合使用,否则还不如使用集合的size方法
long count = stream.count();
System.out.println(count);
//比如 统计有多少个a
stream = strings.stream();
//统计元素个数,一般需要和中间操作结合使用,
count = stream.filter(x ->x.equals("a")).count();
System.out.println(count);
//最大值max 最小值min
List<Integer> list = Arrays.asList(1,3,2,6,53);
Stream<Integer> stream1 = list.stream();
int max =stream1.max((x,y)->x-y).get();
System.out.println(max);
//匹配相关anyMath 匹配数据 比较是否包含
stream1 = list.stream();
//这种需求 contains 就能解决,但是也有contains解决不了的
boolean result = stream1.anyMatch(x->x==5);
System.out.println(result);
//比如所有学生中。判断是否又19岁的
List<Student> students = new ArrayList<Student>();
students.add(new Student("张三",20));
students.add(new Student("李四",22));
students.add(new Student("王三",21));
students.add(new Student("马刘",19));
Stream<Student> stream2 = students.stream();
result = stream2.anyMatch(s->s.age==19);
System.out.println(result);
}
}
class Student{
String name;
int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}