四大内置函数式接口:java.util.function
1.Consumer
2.Function
3.Supplier
4.Predicate
public class Class01_Functional {
public static void main(String[] args) {
//Lambda表达式,消费型接口
testConsumer(1000,m-> System.out.println("酒店吃饭消费"+m));
//函数型接口
System.out.println(testFunction("nishi" ,s->s.trim()));//删除元素前后位置空格
System.out.println(testFunction("nishi" ,s -> s.toUpperCase()));//将元素转为大写
//供给型接口
System.out.println(testSupplier(10,()->(int)(Math.random()*(10-1+1)+1)));
System.out.println(testSupplier(30,()->(int)(Math.random()*(20-10+1)+10)));
//断言型接口
System.out.println(testPredicate(List.of("nini","nin","nishi"),s -> s.length()>=4));
}
//消费型接口,每天固定消费,有参数无返回值
public static void testConsumer(double money , Consumer com){
com.accept(money);
}
//函数型接口,对字符串进行某种处理,返回结果,有参数有返回值
public static String testFunction(String str, Function fun){
return fun.apply(str);
}
//供给型,生成指定个数的不同规则的整数,有返回值,没有参数
public static List testSupplier(int num, Supplier sup){
List list = new ArrayList<>();
for (int i = 1;i testPredicate(List list , Predicate pre){
List newList = new ArrayList<>();
for (String str : list){
if (pre.test(str)){
newList.add(str);
}
}
return newList;//存放满足条件的字符串
}
}
7.7.9方法引用(::)
-
方法引用是lambda表达式的另外一种表现形式 可以通过方法引用简化lambda表达式
-
使用前提: 当lambda表达式的lambda体中的实现已经存在另外一个方法实现了,只需要在lambda体中调用另一个方法--->可以通过方法引用的写法直接引用那个方法 lambda表达式重写的抽象方法的参数列表与返回值对应内部所引用方法的参数列表与返回值 lambda返回值与内部所调用方法的方法直接对应,lambda的参数列表的第一个参数作为内部调用成员方法的对象存在,lambda的第二到多个参数直接匹配内部所调用方法的参数列表存在
-
分类 对象::成员方法 要求: lambda表达式重写的抽象方法的参数列表与返回值对应内部所引用方法的参数列表与返回值 类名::静态方法 lambda表达式重写的抽象方法的参数列表与返回值对应内部所引用方法的参数列表与返回值 类名::成员方法 lambda返回值与内部所调用方法的方法直接对应,lambda的参数列表的第一个参数作为内部调用成员方法的对象存在,lambda的第二到多个参数直接匹配内部所调用方法的参数列表存在
public class Class01_Quite {
public static void main(String[] args) {
//对象::成员方法,消费型接口
PrintStream num = System.out;
Consumer com = i -> num.println(i);
//考虑是否可以通过方法引用简化 : 1)lambda体的实现是否是通过调用另外一个方法实现的--> √ println 2)考虑Consumer中的抽象方法的参数列表与返回值是否对应内部引用println方法的参数列表与返回值--> √
com = num::println;
com = System.out::println;
//List.of(1,2,3,4,5,6).forEach(com);
List.of(1,2,3,4,5,6).forEach(com);
//类名::静态方法
//求两个小数中的最大值
BiFunction fun = (x,y) ->Math.min(x,y);
//分析是否可以通过方法引用简化: 1)lambda体的实现是否是通过调用另外一个方法实现的--> √ max 2)apply方法的参数列表与返回值是否直接匹配内部所调用方法的参数列表与返回值 -> √
fun = Math::min;
System.out.println(fun.apply(1.55,1.68));
BiPredicate pre = (x,y)->x.equals(y);
// 2)lambda返回值与内部所调用方法的方法直接对应,lambda的参数列表的第一个参数作为内部调用成员方法的对象存在,lambda的第二到多个参数直接匹配内部所调用方法的参数列表存在 --> √ 可以使用类名::成员方法名简化
pre = String::equals;
System.out.println(pre.test("你是","你是"));
}
}
7.8Stream流
-
Stream : 关注流式运算,不是传输与存储 io流关注数据的传输 集合与数组关注数据的存储
-
注意: 1.Stream是一次性的流,一旦使用过就不能重复使用 2.Stream的操作不会影响数据源中的数据 3.延迟执行|惰性加载: 当获取终止行为时候才会执行中间操作
-
使用步骤: 1.获取Stream流 2.中间行为 : 一系列的流式操作 3.终止行为
-
创建Stream的方式: 1.Collection Stream
stream() 2.Arrays stream() 3.Stream.of(值列表) -
特点: 1.Stream本身不存储数据 2.Stream不会修改数据源中的数据,可以对根据数据源产生的数据进行一些列流式的中间操作,每次中间操作都会返回一个持有结果的新的流 3.流是一次性的流,一旦使用就被销毁,不能重复使用多次 4.惰性加载|延迟执行: 只有在获取终止行为|结果的时候才会一起执行
public class Class01_Stream {
public static void main(String[] args) {
//1..Collection Stream stream()
List list = List.of(1, 2, 3, 4, 5);
Stream stream = list.stream();
//增强for遍历
stream.forEach(System.out::println);
//2.Arrays stream()
String[] srr = {"AAA", "BBB", "CCC"};
Stream stream1 = Arrays.stream(srr);
//增强for遍历
stream1.forEach(System.out::println);
//3.Stream.of(值列表)
Stream stream2 = Stream.of(5,4,3,2,1);
stream2.forEach(System.out::println);
}
}
7.8.1Stream流中间操作
-
1.过滤 Stream
filter(Predicate super T> predicate); 2.去重 Stream distinct() 3.截取 Stream limit(long maxSize) 4.跳过 Stream skip(long) 5.排序 sorted() | sorted(Comparator super T> comparator) 6.映射 map(Function) :接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。 -
注意: 中间操作都会返回一个持有结果的新的流
-
1,Stream 中间操作 映射 map() 将流操作的元素装换成另外一种形式|提取结果. ** 接收一个函数作为参数,该函数会被应用到stream操作的每一个元素上,得到结果,最终会返回一个持有所有结果的新的stream {"","",""} {19,18,17,20},{{'a','a','a'},{'b','b','b'},{'c','c','c'}} flatMap()
2, 接收一个函数作为参数,该函数会被应用到stream操作的每一个元素上,得到结果必须为一个stream,最终会把所有的stream汇总成一个流,返回 {1,2,3},{4,5,6},{7,8,9}=>{1,2,3,4,5,6,7,8,9}
public class Class01_Stream2 {
public static void main(String[] args) {
List list = Arrays.asList(
new Employee("老李",21,3000),
new Employee("老范",22,4000),
new Employee("老吴",22,5000),
new Employee("老吴",22,5000)
);
//1.获取一个stream
Stream stream = list.stream();
//2.中间操作延迟执行
stream = stream.filter(e->{
System.out.println("----过滤条件----");
return e.getSal()>3000;
//中间操作方法
}).distinct()
.limit(2)
.skip(1)
//最终过滤
.filter(e->{
System.out.println("----最终过滤----"+e);
return true;
});
//排序
stream = list.stream().sorted();
stream = list.stream().sorted((x,y)->Double.compare(x.getSal(), y.getSal()));
//映射
//Stream stream2 = list.stream().map(e->e.getSal());
Stream stream2 = list.stream().map(Employee::getSal);
//终止行为
stream2.forEach(System.out::println);
}
}
7.8.2终止行为
-
1,查找与匹配 allMatch-检查是否匹配所有元素 anyMatch-检查是否至少匹配一个元素 noneMatch-检查是否没有匹配所有元素
-
findFirst-返回第一个元素 findAny-返回当前流中的任意元素 count-返回流中元素的总个数 max-返回流中最大值 min-返回流中最小值
public class Class01_Stream3 {
static List list = Arrays.asList(
new Employee("老李",21,3000),
new Employee("老范",22,4000),
new Employee("老吴",22,6000),
new Employee("老王",25,5000),
new Employee("老楚",23,3900)
);
public static void main(String[] args) {
//1.获取一个stream
Stream stream = list.stream();
//2.中间操作,终止行为
//anyMatch-检查是否至少匹配一个元素
System.out.println(stream.allMatch(e->e.getAge()>=21));
//需求:按工资排序,获取第一个员工信息
// findFirst-返回第一个元素
//1)降序排序 2)找到第一个元素
Optional op1 = list.stream().sorted((x,y)->Double.compare(y.getSal(), x.getSal())).findAny();
//判断里面是否有元素
if (op1.isPresent()){
System.out.println(op1.get());
}
//并行流
op1 = list.parallelStream().findAny();
System.out.println(op1.get());
//薪资>5000的员工个数
// count-返回流中元素的总个数
System.out.println(list.stream().filter(e->e.getSal()>5000).count());
max-返回流中最大值
min-返回流中最小值
System.out.println(list.stream().min((x,y)->Double.compare(x.getSal(), y.getSal())).get());
//规约 map-reduce 先加工->后处理汇总结果
System.out.println(list.stream().map(Employee::getSal).reduce((x,y)->x+y).get());
System.out.println(Stream.of(1,2,3,4,5,6).reduce((x,y)->{
System.out.println("----->x ="+x+",y= "+y);
return (x+y);
}).get());
//算元素的总数
System.out.println(Stream.of(1,2,3,4,5,6).reduce(10,(x,y)->{
System.out.println("----->x ="+x+",y= "+y);
//返回元素的和
return (x+y);
}));
// 收集(collect)
//collect 主要依赖 java.util.stream.Collectors 类内置的静态方法。
//Collectors.toList(),输出集合里面所有的姓名
List name = list.stream().distinct().map(Employee::getName).collect(Collectors.toList());
//打印输出
System.out.println(name);
//Collectors.toSet(),输出集合里面所有的姓名
Set name2 = list.stream().map(Employee::getName).collect(Collectors.toSet());
System.out.println(name2);
Collectors.toMap(),输出集合里面所有的姓名和工资
Map map = list.stream().distinct().collect(Collectors.toMap(Employee::getName,Employee::getSal));
System.out.println(map);
}
}
7.8.3终止行为约束reduce
-
1, 规约 reduce 根据某个统一的规则对数据进行合并
注意: map-reduce 先加工再合并
public class Class005_Stream {
public static void main(String[] args) {
List list = List.of(
new Employee("zhangsan",18,1),
new Employee("lisi",17,2),
new Employee("hanjiu",19,3),
new Employee("tainqi",21,4),
new Employee("heiba",18,5),
new Employee("wangwu",19,7654),
new Employee("wangwu",19,7654),
new Employee("zhaoliu",16,5321)
);
//计算前五个员工的薪资总和
//reduce(BinaryOperator) 把stream操作的前两个元素作为第一次运算的两个参数,得到的结果作为第二次运算的第一个参数,stream操作的下一个元素作为第二次运算的第二个参数,,得到的结果作为第三次运算的第一个参数.....
System.out.println(list.stream().limit(5).map(Employee::getSalary).reduce((x,y)->x+y).get());;
//reduce(BinaryOperator) 把stream操作的前两个元素作为第一次运算的两个参数,得到的结果作为第二次运算的第一个参数,stream操作的下一个元素作为第二次运算的第二个参数,,得到的结果作为第三次运算的第一个参数.....
System.out.println(list.stream().limit(5).map(Employee::getSalary).reduce(100.0,(x,y)->x+y));;
// -->前提要求必须为并行流才有效
//U reduce(U identity, --> 其实值
// BiFunction accumulator, 先加工: 先对流操作的每一个数据与起始值进行一次运算,得到结果
// BinaryOperator combiner); 合并,对上一步加工得到的结果进行合并
System.out.println(list.stream().limit(5).map(Employee::getSalary).parallel().reduce(100.0,
(x,y)->{
System.out.println(Thread.currentThread().getName()+"----- : "+x+"----->"+y);
return x+y;
},
(x,y)->{
System.out.println(Thread.currentThread().getName()+"----- : "+x+"---+--"+y+" = "+(x+y));
return x+y;
}));;
}
}
7.8.4终止行为收集
-
1, 收集 collect(Collector) Collectors 实现各种有用的约简操作的Collector的实现,例如将元素累积到集合中,根据各种标准汇总元素等。
public class Class006_Stream {
public static void main(String[] args) {
List list = List.of(
new Employee("zhangsan",18,1),
new Employee("lisi",17,2),
new Employee("hanjiu",19,3),
new Employee("tainqi",21,4),
new Employee("heiba",18,5),
new Employee("wangwu",19,6),
new Employee("zhaoliu",16,7)
);
//toList()
//收集所有员工得到姓名
System.out.println(list.stream().map(Employee::getName).collect(Collectors.toList()));;
//去重
System.out.println(list.stream().map(Employee::getName).collect(Collectors.toSet()));;
//toMap
System.out.println(list.stream().filter(e->e.getAge()>18).distinct().collect(Collectors.toMap(Employee::getName,Employee::getAge)));;
//counting()
System.out.println(list.stream().collect(Collectors.counting()));
System.out.println(list.stream().collect(Collectors.maxBy((x,y)->Double.compare(x.getSalary(),y.getSalary()))));
//薪资平局值
System.out.println(list.stream().collect(Collectors.averagingDouble(Employee::getSalary)));
}
}



