1.方法引用
若Lambda体中的内容有方法已经实现了,我们可以使用“方法引用”(可以理解为方法引用是Lambda 表达式的另一种表现形式,简化Lambda表达式),主要有三种语法格式:
注:Lambda表达式可以使用方法引用的前提是以下两点:
1)lambda体的实现是否是通过调用了另外一个方法实现的 --> √
2)内部所引用方法的返回值是否与lambda的返回值保持一致 --> √
(1)对象::实例方法名
//实例代码-方法的引用(对象::实例方法名)
public class Class002_FunctionQuite {
public static void main(String[] args) {
test1();
}
//对象::成员方法名
public static void test1(){
List<Integer> list = List.of(1,2,3,4,5);
list.forEach(x->{
System.out.println(x);
});
PrintStream ps = System.out;
list.forEach(x->{
ps.println(x);
});
/*
分析:
1)lambda体的实现是否是通过调用了另外一个方法实现的 --> √
2)内部所引用方法的返回值是否与lambda的返回值保持一致 --> √
*/
list.forEach(ps::println);
list.forEach(System.out::println);
}
}
(2)类::静态方法名
//实例代码-方法引用(类名::静态方法名)
public class Class002_FunctionQuite {
public static void main(String[] args) {
test2();
}
//类名::静态方法名
public static void test2(){
//求两个数中最大的值
//BiFunction<Integer,Integer,Integer> function = (x,y)-> Math.max(x,y);
/*
分析:
1)lambda体的实现是否是通过调用了另外一个方法实现的 --> √
2)内部所引用方法的返回值是否与lambda的返回值保持一致 --> √
*/
BiFunction<Integer,Integer,Integer> function = Math::max;
System.out.println(function.apply(100,101));;
//Comparator<Integer> com = (x,y) -> {return Integer.compare(x,y);};
/*
分析:
1)lambda体的实现是否是通过调用了另外一个方法实现的 --> √
2)内部所引用方法的返回值是否与lambda的返回值保持一致 --> √
*/
Comparator<Integer> com = Integer::compareTo;
System.out.println(com.compare(18,18));;
}
}
(3)类::实例方法名
//实例代码-(类名::成员方法名)
public class Class002_FunctionQuite {
public static void main(String[] args) {
test3();
}
//类名::成员方法名
public static void test3(){
//BiPredicate<String,String> pre = (x,y)-> x.equals(y);
/*
分析: 通过类名::成员方法名 简化lanbda结构
1)lambda体的实现是否是通过调用了另外一个方法实现的 --> √
2) 内部所引用方法的返回值与lambda的返回值相同
lambda参数列表的第一个参数作为内部引用成员方法的对象存在
lmabda参数列表的第二个参数开始(如果有的话)作为内部引用方法的参数列表
*/
BiPredicate<String,String> pre = String::equals;
System.out.println(pre.test("张三","张三封"));;
}
}
2.Stream流
Java 8中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、 高效的聚合操作(aggregate operation),或者大批量数据操作 (bulk data operation)。
Stream流:
根据数据源所产生的的元素序列
数据源: 集合,数组 ---> 侧重点在数据的存储
stream流: -->关注数据的计算
注意: 1.流本身不能存储数据
2.流不能修改数据源中的数据
3.流是一次性的流,流是式操作的每一步都会返回一个持有结果的新流
4.延迟执行|惰性加载 : 当不进行终止行为时候,不会执行流式中间操作
Stream的操作三个步骤
1、创建Stream
一个数据源(如:集合、数组),获取一个流
2、中间操作
一个中间操作链,对数据源的数据进行处理
3、终止操作
一个终止操作,执行中间操作链,并产生结果
(1)创建流(流分为顺序流和并行流)
//实例代码-创建流
public class Class001_Stream {
public static void main(String[] args) {
//1.Collection--> stream
List<Integer> list = new ArrayList<>();
//顺序流
Stream<Integer> stream = list.stream();
//并行流
Stream<Integer> stream2 = list.parallelStream();
System.out.println(stream2);
//2) Arrays.stream(array)
Stream stream3 = Arrays.stream(new String[]{"1"});
System.out.println(stream3);
//3)Stream.of(数据1,数据2,数据3...)
Stream stream4 = Stream.of("a","b");
stream4.forEach(System.out::println);
//4)Stream.of(数组)
Stream stream5 = Stream.of(new String[]{"abc","bcd"});
stream5.forEach(System.out::println);
}
}
(2)Stream的中间操作
多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何 的处理,而在终止操作时一次性全部处理,称为”惰性求值”。
筛选和切片:
filter-接收Lambda,从流中排除某些元素
limit-截断流,使其元素不超过给定数量
skip-跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个空流
distinct-筛选,通过流所生产元素的hashCode()和equals()去除重复元素
//实例代码-Stream的中间操作(筛选和切片)
public class Class002_Stream {
static List<Employee> emps = Arrays.asList(
new Employee(102,"张三", 18, 3333.33),
new Employee(101,"李四", 38, 4444.44),
new Employee(104,"王五", 50, 5555.55),
new Employee(104,"王五", 50, 5555.55),
new Employee(103,"赵六", 16, 6666.66),
new Employee(105,"田七", 28, 7777.77)
);
public static void main(String[] args) {
//1.获取流
Stream<Employee> stream = emps.stream();
//2.中间操作
Stream<Employee> stream1 = stream
.filter(e->{
//System.out.println("--中间过滤操作--->"+e);
return e.getAge()>=18;
})
.distinct()//去重
.limit(3)//截断流,使其元素不超过给定数量
.skip(1)//跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个空流。
//3.终止行为
stream1.forEach(System.out::println);
}
}
排序 :
sorted(Comparable)-自然排序
sorted(Comparator)-定制排序
//实例代码-Stream的中间操作(排序)
public class Class002_Stream {
static List<Employee> emps = Arrays.asList(
new Employee(102,"张三", 18, 3333.33),
new Employee(101,"李四", 38, 4444.44),
new Employee(104,"王五", 50, 5555.55),
new Employee(104,"王五", 50, 5555.55),
new Employee(103,"赵六", 16, 6666.66),
new Employee(105,"田七", 28, 7777.77)
);
public static void main(String[] args) {
//1.获取流
Stream<Employee> stream = emps.stream();
//2.中间操作
Stream<Employee> stream1 = stream
.filter(e->{
//System.out.println("--中间过滤操作--->"+e);
return e.getAge()>=18;
})
//.sorted(); //默认根据内部比较器
.sorted((x,y)->Double.compare(y.getPrice(), x.getPrice()));
//3.终止行为
stream1.forEach(System.out::println);
}
}
映射:
map : 将stream操作的每一个元素都作用与实参传递的函数,映射一个结果,返回操作结果的流(重要)
flatMap : 将stream操作的每一个元素都作用与实参传递的函数,映射一个结果,结果必须为一个流,最终返回所有结果流结合以后的一个流(了解)
//实例代码-Stream的中间操作(映射map)
public class Class003_map {
static List<Employee> emps = Arrays.asList(
new Employee(102,"张三", 18, 3333.33),
new Employee(101,"李四", 38, 4444.44),
new Employee(104,"王五", 50, 5555.55),
new Employee(104,"王五", 50, 5555.55),
new Employee(103,"赵六", 16, 6666.66),
new Employee(105,"田七", 28, 7777.77)
);
public static void main(String[] args) {
//1.获取流
Stream<Employee> stream = emps.stream();
//2.中间操作
//1) 获取员工姓名的流
Stream<String> stream1 = stream
.map(employee -> employee.getName())
.distinct();
List<String> list = List.of("aaa","bbb","ccc");
Stream<Character> stream2 = list.stream()
.map(Class003_map::getCharacterStream); //[[a,a,a],[b,b,b],[c,c,c]]
//3.终止行为
stream1.forEach(System.out::println);
//流中操作流
stream2.forEach(s->{
s.forEach(System.out::println);
});
stream2.forEach(System.out::println);
}
}
(3)终止操作
查找与匹配
//实例代码-Stream的终止操作(查找与匹配)
public class Class004_Stream {
static List<Employee> emps = Arrays.asList(
new Employee(102,"张三", 18, 3333.33),
new Employee(101,"李四", 38, 4444.44),
new Employee(104,"王五", 50, 5555.55),
new Employee(104,"王五", 50, 5555.55),
new Employee(103,"赵六", 16, 6666.66),
new Employee(105,"田七", 28, 7777.77)
);
public static void main(String[] args) {
//获取流
Stream<Employee> stream = emps.stream();
//终止行为
System.out.println(stream.allMatch(e->e.getAge()>=18));
// 需求:找到员工工资最高的员工信息
//1)按照工资做降序排序
//找到第一个
Optional<Employee> op = emps.stream().sorted((x, y)->Double.compare(y.getPrice(),x.getPrice())).findFirst();
System.out.println(op.get());
//findAny-返回当前流中的任意元素
System.out.println(emps.parallelStream().findAny().get());
System.out.println(emps.stream().parallel().findAny().get());
//count-返回流中元素的总个数
System.out.println(emps.stream().filter(e->e.getPrice()>=5000).distinct().count());
//2)max()
System.out.println(emps.stream().max((x,y)->Double.compare(x.getPrice(),y.getPrice())).get());;
//找到薪资最高的薪资值 System.out.println(emps.stream().map(Employee::getPrice).max(Double::compareTo).get());;
需求:获取当前公司所有员工的姓名添加到集合中
//toList()
List<String> list = emps.stream()
.map(Employee::getName)
.collect(Collectors.toList());
list.forEach(System.out::println);
//toSet()
Set<Double> set = emps.stream()
.map(Employee::getPrice)
.collect(Collectors.toSet());
set.forEach(System.out::println);
//toMap() System.out.println(emps.stream().distinct().collect(Collectors.toMap(Employee::getId,Employee::getName)));;
工资总和 System.out.println(emps.stream().collect(Collectors.summingDouble(Employee::getPrice)));;
}
}