1.Lambda
- 匿名函数,Lambad表达式可以理解为一段可以传递的代码(将代码像数据一样传递)
- 格式:
- -> : lambda操作符
- -> 左边: 形参列表(其实就是接口中的抽象方法的形参列表)
- ->右边: lambda体(其实就是重写的抽象方法的方法体)
- 使用:(六种情况)
- 1.无参无返回值
- 2.lambda需要一个参数,但是没有返回值
- 3.数据类型可以省略,因为可由编辑器推断得出,称为"类型推断"
- 4.只需要一个参数时,参数的小括号可以省略
- 5.需要两个或以上的参数,多条执行语句,并且可以有返回值
- 6.lambda只有1条语句时,return和{}都可以省略
- 总结:
- 左边:形参列表的参数类型可以省略(类型推断);如果只有一个参数,()也可以省略
- 右边:lambda {}在只有一条语句时(可能是return语句)可以省略,return关键字也要省略
- 本质:作为函数式接口的一个实例(一定是借助接口存在)
- 接口是只能有一个抽象方法
- 以前用匿名实现类表示的现在都可以用Lambda表达式来写
- 引入
package Lambda;
import org.junit.Test;
import java.util.Comparator;
public class LambdaTest {
@Test
public void test1() {
Runnable r1= new Runnable() {
@Override
public void run() {
System.out.println("我爱北京天安门");
}
};
r1.run();
//---------------------------------------------
Runnable r2= ()-> System.out.println("我爱北京天安门");
r2.run();
}
@Test
public void test2() {
Comparator<Integer> com1 = new Comparator<Integer>() {
@Override
public int compare(Integer s1, Integer s2) {
return Integer.compare(s1,s2);
}
};
int res1=com1.compare(12,18);
System.out.println(res1);
System.out.println("**************");
//Comparator接口中只有比较的这个方法,所以这些步骤可以是省略
Comparator<Integer> com2 = (s1, s2) -> Integer.compare(s1,s2);
int res2=com2.compare(1282,181);
System.out.println(res2);
System.out.println("**************");
//更简洁写法:方法引用
Comparator<Integer> com3 = Integer::compare;
int res3=com2.compare(1282,181);
System.out.println(res3);
}
}
-----------------------------------------------------------------------------------------------------
package Lambda;
import org.junit.Test;
import java.util.Comparator;
import java.util.function.Consumer;
public class LambdaTest {
@Test
//1.无参无返回值
public void test1() {
Runnable r1 = new Runnable() {
@Override
public void run() {//看方法
System.out.println("我爱北京天安门");
}
};
r1.run();
//---------------------------------------------
System.out.println("------------------");
Runnable r2 = () -> {
System.out.println("我爱北京天安门");
};
r2.run();
}
//2.lambda需要一个参数,但是没有返回值
@Test
public void test2() {
Consumer<String> con =new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
con.accept("雅黑发放表");
System.out.println("------------------");
Consumer<String> con1 = (String s) -> {
System.out.println(s);
};
con1.accept("哈哈哈哈");
}
//3.数据类型可以省略,因为可由编辑器推断得出,称为"类型推断"
//在列表创建中可以知道
@Test
public void test3() {
Consumer<String> con1 = (String s) -> {
System.out.println(s);
};
con1.accept("哈哈哈哈");
System.out.println("------------------");
Consumer<String> con2 = (s) -> {//类型推断,可以省略
System.out.println(s);
};
con2.accept("哈哈哈哈");
}
//4.只需要一个参数时,参数的小括号可以省略
@Test
public void test4() {
Consumer<String> con1 = (s) -> {//类型推断,可以省略
System.out.println(s);
};
con1.accept("哈哈哈哈");
System.out.println("-----------------------------");
Consumer<String> con3 = s -> {//少了小括号
System.out.println(s);
};
con3.accept("哈哈哈哈");
}
//5.需要两个或以上的参数,多条执行语句,并且可以有返回值
@Test
public void test5() {
Comparator<Integer> com1 = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
System.out.println(o1);
System.out.println(o2);
return o1.compareTo(o2);
}
};
System.out.println(com1.compare(1,3));
System.out.println("-----------------------------");
Comparator<Integer> com2= (o1,o2) ->{
System.out.println(o1);
System.out.println(o2);
return o1.compareTo(o2);
};
System.out.println(com2.compare(12,3));
}
//6.lambda只有1条语句时,return和{}都可以省略
@Test
public void test6() {
Comparator<Integer> com1= (o1,o2) ->{
return o1.compareTo(o2);
};
System.out.println(com1.compare(12,3));
System.out.println("-----------------------------");
Comparator<Integer> com2= (o1,o2) ->o1.compareTo(o2);
System.out.println(com2.compare(12,3));
}
@Test
public void test7() {
Consumer<String> con1 = (s) -> {//类型推断,可以省略
System.out.println(s);
};
con1.accept("哈哈哈哈");
System.out.println("-----------------------------");
Consumer<String> con3 = s -> System.out.println(s);
con3.accept("哈哈哈哈");
}
}
2.函数式接口
- 如果一个接口中,只声明了一个抽象方法,则此接口就称为函数式接口
- 在接口上使用@FunctionalInterface注解,这样做可以检查它是否是一个函数式接口,同时javadoc也会包含一条声明,说明这个接口是一个函数式接口
- 何时使用函数式接口
- 如果我们开发中需要定义一个函数式接口,首先看看在已有的jdk提供的函数式接口是否提供了能满足需求的函数式接口 ,如果有直接调用,不需要自己定义了
- 自定义函数式接口
package Lambda;
@FunctionalInterface
public interface MyInterface {
void method1();
}
- java内置四大核心函数式接口
函数式接口 | 参数类型 | 返回类型 | 用途 |
---|---|---|---|
Consumer 消费型接口 | T | void | 对对象为T的对象应用操作, 包含方法 : void accept(T t) |
Supplier供给型接口 | 无 | T | 返回类型为T的对象,包含方法: T get() |
Function<T,R> 函数型 | T | R | 对对象为T的对象应用操作,并返回结果.结果是R类型的对象,包含方法: R apply(T t) |
Predicate 断定型 | T | bollean | 确定对象是否满足约束,并返回boolean值.包含方法:boolean test(T t) |
package Lambda;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;
/**java 内置4大核心函数式接口
* 1.消费型接口 Consumer<T> void accept(T t)
* 2.供给型接口 Supplier<T> T get()
* 3.函数型接口 Function<T,R> R apply(T t)
* 4.断言型接口 Predicate<T> boolean test(T t)
*/
public class LambdaFunctionTest {
@Test
public void test1(){
happyTime(100,new Consumer<Double>(){
@Override
public void accept(Double aDouble) {
System.out.println("消费"+aDouble);
}
});
System.out.println("*******************************");
happyTime(100,money -> System.out.println("消费"+money));
}
public void happyTime(double money, Consumer<Double> con){
con.accept(money);
}
@Test
public void test2(){
List<String> list = Arrays.asList("aaa","bb","ccc","ddd");
List<String> filterString =
filterString(list, new Predicate<String>() {
@Override
public boolean test(String s) {
return s.length() > 2;
}
});
System.out.println(filterString);
System.out.println("*******************************");
List<String> filterString2 =filterString(list,s -> s.length() <3);
System.out.println(filterString2);
}
//根据给定的规则,过滤结合汇总的字符串,此规则由Predicate的方法决定
public List<String> filterString(List<String> list, Predicate<String> pre){//集合根据某种规则来做一个过滤
ArrayList<String> filterList= new ArrayList<>();
for(String s:list){
if(pre.test(s)){
filterList.add(s);
}
}
return filterList;
}
}
3.方法应用和构造器引用
- 使用情景:当要传递个Lambda体的操作,已经有实现的方法了,可以使用方法引用
- 可以看做Lambda表达式的深层次的表达
- 本质上就是Lambda表达式,而Lambda表达式作为函数式接口的实例,所以方法引用也是函数表达式的接口
- 使用: ==类/对象 : : 调用的方法名 ==
- 分三种情况:
- 对象 : : 非静态方法
- 类 : : 非静态方法
- 类 : : 静态方法
- 要求:
- 要求接口中的抽象方法的形参列表和返回值类型 与方法引用的方法的形参列表和返回值类型相同(情况1,2)
- 当函数式接口方法的第一个参数是需要引用方法的调用者,并且第二个参数是需要引用地方免费参数(或无参数)时:ClassName::methodName(情况3)
方法引用
package MethodTest;
import org.junit.Test;
import java.io.PrintStream;
import java.util.Comparator;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
public class MethodTest {
//1.对象 :: 实例方法
//Consumer 中的void accept(T,t) 接口中的形参列表返回类型
//PrintStream中的void println(T t) 与这个类的形参列表返回类型一致
@Test
public void test1() {
Consumer<String> con1 = str -> System.out.println(str);
con1.accept("哈哈");
System.out.println("--------------------------------");
PrintStream ps=System.out;//对象//非静态方法用对象去调用
Consumer<String> con2 = ps::println;
con2.accept("呵呵");
}
//Supplier 中的 T get()
//Employee 中的String getName()
@Test
public void test2(){//什么也不放,但是返回值
Employee emp = new Employee(1,"QQ",23,000);
Supplier<String> sup1 = () -> emp.getName();//对象//非静态方法用对象去调用
System.out.println(sup1.get());
System.out.println("--------------------------------");
Supplier<String> sup2 = emp::getName;
System.out.println(sup2.get());
//本身这个方法有一个抽象方法已经实现,而且参数列表返回类型一样
}
//2.类 :: 静态方法
//Comparator 中的int compare(T t1,T t2)
//Integar 中的int compare(T t1,T t2)
@Test
public void test3(){
Comparator<Integer> com1= (t1, t2) -> Integer.compare(t1,t2);
System.out.println(com1.compare(12,21));
System.out.println("--------------------------------");
Comparator<Integer> com2 = Integer::compare;//不用写括号方原因是因为,参数与形参列表的参数一样
System.out.println(com2.compare(12,21));
}
//Function 中的 R apply(T t)
//Math 中的Long round(double d)
@Test
public void test4(){
Function<Double ,Long> funn2 = new Function<Double, Long>() {
@Override
public Long apply(Double d) {
return Math.round(d);
}
};
Function<Double,Long> func1 = d-> Math.round(d);
System.out.println(func1.apply(12.3));
System.out.println("--------------------------------");
Function<Double,Long> func2 = Math::round;
System.out.println(func2.apply(12.3));
}
//3.类 :: 实例方法 (难)
//Comparator 中的int compare(T t1,T t2)
//String 中的int t1.compareTo(t2) //变为调用者
@Test
public void test5(){
Comparator<String> com1 = (s1,s2) -> s1.compareTo(s2);
System.out.println(com1.compare("abc","abd"));
System.out.println("--------------------------------");
Comparator<String> com2 = String::compareTo;
System.out.println(com2.compare("abc","abm"));
}
//BiPrecdicate 中的boolean test(T t1,T t2)
//String 中的boolean t1.equals(t2)
@Test
public void test6(){
BiPredicate<String,String> bp1 = (s1, s2) -> s1.equals(s2);
System.out.println(bp1.test("abc","abc"));
System.out.println("--------------------------------");
BiPredicate<String,String> bp2 = String::equals;
System.out.println(bp2.test("abc","abc"));
}
//Function 中的R apply(T t)
//Employee 中的String getName()
@Test
public void test7(){
Employee employee = new Employee(1001,"hh",12,120.1);
Function<Employee,String> fun1 = (e) -> e.getName();
System.out.println(fun1.apply(employee));
System.out.println("--------------------------------");
Function<Employee,String> fun2 = Employee::getName;
System.out.println(fun2.apply(employee));
}
}
构造器引用
package MethodTest;
import org.junit.Test;
import java.util.Arrays;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
/**
* 1.构造器引用
* 和方法引用类似,函数式接口的抽象方法的形参列表和构造器的形参列表一样
* 抽象方法的返回值类型即为构造器所属的类的类型
* 2.数组引用
* 可以把数组看做应该特殊的类,则写法与构造器引用一样
*
*/
public class ConstructtoRefTest {
//构造器引用 类名::new
//Supplier 中的T get()
//无参有返回值
//Employee的空参构造器 :Employee()
//抽象方法有一个返回值T,T就是要创建的类型的对象
@Test
public void test1() {
Supplier<Employee> sup = new Supplier<Employee>() {
@Override
public Employee get() {
return new Employee();
}
};
System.out.println("*************************");
Supplier<Employee> sup1 = () -> new Employee();
System.out.println(sup1.get());
System.out.println("*************************");
Supplier<Employee> sup2 = Employee::new;
System.out.println(sup2.get());
}
//Function 中的R apply(T t)
@Test
public void test2() {
Function<Integer, Employee> fun1 = id -> new Employee(id);
Employee employee = fun1.apply(1001);
System.out.println(employee);
System.out.println("*************************");
Function<Integer, Employee> fun2 = Employee::new;
Employee employee1 = fun2.apply(1002);
System.out.println(employee1);
}
//BiFunction 中的R apply(T t,U u)
@Test
public void test3() {
BiFunction<Integer, String, Employee> fun1 = (id, name) -> new Employee(id, name);
System.out.println(fun1.apply(1001, "Tom"));
System.out.println("*************************");
BiFunction<Integer, String, Employee> fun2 = Employee::new;
}
//2.数组引用 数组类型[] :: new
@Test
public void test4() {
//长度
Function<Integer, String[]> fun1 = length -> new String[length];
String[] arr1 = fun1.apply(10);
System.out.println(Arrays.toString(arr1));
System.out.println("*************************");
Function<Integer, String[]> fun2 = String[]::new;
String[] arr2 = fun2.apply(20);
System.out.println(Arrays.toString(arr2));
}
}
4.StreamAPI
- Stream与Collection集合的区别:Collection是一种静态的内存数据机构,面向内存,存储在内存中;Stream是有关于计算,面向CPU,通过CPU实现计算.
- 注意:
Stream不会自己存储元素
不会改变源对象,会返回一个持有结果的新Stream
操作是延迟执行的,意味着他们会等到需要结果的时候才执行
步骤:
1.创建Stream
- 一个数据源(如:集合,数组),获取一个流
2.中间操作
- 一个中间操作(过滤,映射等)链,对数据源的数据进行处理
3.终止操作
- 一旦执行终止操作,就执行中间操作链,并产生结果,之后就不会再被使用
package StreamAPI;
//1.对数据的运算,与CPU
//集合对数据的存储,与内存
import MethodTest.Employee;
import MethodTest.EmployeeData;
import org.junit.Test;
import java.util.Arrays;
import java.util.List;
import java.util.stream.IntStream;
import java.util.stream.Stream;
/**
*
*/
public class StreamTest {
//创建方式:
// 1.通过集合
//default Stream<E> stream() :返回一个顺序流
//default Stream<E> parallelStream() :返回一个并行流
@Test
public void test1(){
List<Employee> employees = EmployeeData.getEmployees();
//返回一个顺序流
Stream<Employee> stream = employees.stream();
//返回一个并行流
Stream<Employee> parallelStream = employees.parallelStream();
}
// 2.通过数组
//调用Arrays类中的static <T> Stream<T> stream(T[] array):返回一个流
//通过泛型来识别类型
@Test
public void test2(){
int[] arr = new int[]{1,2,3,4,5,6};
IntStream stream =Arrays.stream(arr);
Employee e1= new Employee(1001,"Tom",23,5600);
Employee e2= new Employee(1002,"Jerry",34,6600);
Employee[] arr1 = new Employee[]{e1,e2};//静态初始化
Stream<Employee> stream1 = Arrays.stream(arr1);
}
// 3.通过Stream的of()
@Test
public void test3(){
Stream<String> stream = Stream.of("aa", "bb", "cc", "dd");//包装类对象
}
// 4.创建无限流(不常用)
//4.1 迭代
//public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)
//4.2 生成
//public static<T> Stream<T> generate(Supplier<T> s)
@Test
public void test4(){
//迭代
//遍历前10个偶数
Stream.iterate(0,t-> t+2).limit(10).forEach(System.out::println);
//生成
Stream.generate(Math::random).limit(10).forEach(System.out::println);
}
}
---------------------------------------------------------------------------------------------------------------------------------------------
package StreamAPI;
import MethodTest.Employee;
import MethodTest.EmployeeData;
import org.junit.Test;
import java.util.List;
import java.util.stream.Stream;
/**
* 测试Stream的中间操作
*/
public class StreamTest1 {
//1.筛选与切片
/**
* filter(Predicate p)——接收Lambda,从流中排除某些元素
* limit(long maxSize)——截断流,使其元素不超过给定数量
* skip(long n)——跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流。与limit(n)互补
* distinct()——筛选,通过流所生成元素的hashCode()和equals()去除重复元素
*/
// 1.1filter
@Test
public void test1(){
List<Employee> list = EmployeeData.getEmployees();
Stream<Employee> stream= list.stream();
//查询员工表>1000
stream.filter(e->e.getSalary()>1000).forEach(System.out::println);
//一旦执行终止操作,stream流就会关闭,不可以再次使用
// 1.2limit()
System.out.println("limit()----------------");
//重新调用
list.stream().limit(3).forEach(System.out::println);
// 1.3skip()//跳过前面的数据
System.out.println("skip()----------------");
list.stream().skip(3).forEach(System.out::println);
// 1.4distinct()//去 重
System.out.println("distinct()----------------");
list.add(new Employee(1010,"张三",23,9999.99));
list.add(new Employee(1010,"张三",23,9999.99));
list.add(new Employee(1010,"张三",23,9999.99));
list.add(new Employee(1010,"张三",23,9999.99));
list.add(new Employee(1010,"张三",23,9999.99));
list.stream().distinct().forEach(System.out::println);
}
}
---------------------------------------------------------------------------------------------------------------------------------------------
package StreamAPI;
//2.映射
import MethodTest.Employee;
import MethodTest.EmployeeData;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
/**
* map(Function f) 接收一个函数作为参数,将元素转换成其他形式或提取信息,该函数,会被应用到每个元素上,并将其映射成一个新的元素
* flatMap(Function f) 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
*/
public class StreamTest2 {
//map(Function f) 接收一个函数作为参数,将元素转换成其他形式或提取信息,该函数,会被应用到每个元素上,并将其映射成一个新的元素
//类似于add
@Test
public void test1(){
List<String> list= Arrays.asList("aaa","bbb","ccc");
list.stream().map(str->str.toUpperCase()).forEach(System.out::println);
System.out.println("----------------");
List<Employee> employees= EmployeeData.getEmployees();
//练习1.获取员工姓名长度 的员工姓名
Stream<String> nameStream=employees.stream().map(Employee::getName);
nameStream.filter(name ->name.length()>3).forEach(System.out::println);
System.out.println("----------------");
//练习2
Stream<Stream<Character>> streamStream=list.stream().map(StreamTest2::fromStringToStream);
streamStream.forEach(s->s.forEach(System.out::println));
System.out.println("----------------");
//flatMap(Function f) 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
//类似于addALl
Stream<Character> characterStream = list.stream().flatMap(StreamTest2::fromStringToStream);
characterStream.forEach(System.out::println);
}
@Test
public void test2(){
}
@Test
public void test3(){
ArrayList list1=new ArrayList();
list1.add(1);
list1.add(2);
ArrayList list2=new ArrayList();
list2.add(3);
list2.add(4);
// list1.add(list2);
list1.addAll(list2);
System.out.println(list1);
}
//将字符串中的多个字符构成的集合转换为响应的Stream的实例
public static Stream<Character> fromStringToStream(String str){
ArrayList<Character> list = new ArrayList<>();
for (Character c : str.toCharArray()) {
list.add(c);
}
return list.stream();
}
}
--------------------------------------------------------------------------------------------------------------------------------------------
package StreamAPI;
import MethodTest.Employee;
import MethodTest.EmployeeData;
import org.junit.Test;
import java.util.Arrays;
import java.util.List;
//3.排序
/**
* sorted() 自然排序
* sorted(Comparator com) 定制排序
*/
public class StreamTest3 {
@Test
public void test1(){
//sorted
List<String> list = Arrays.asList("ccc","aaa","bbb","ddd","eee");
list.stream().sorted().forEach(System.out::println);
//抛异常,原因:Employee没有实现Comparable接口
// List<Employee> employees = EmployeeData.getEmployees();
// employees.stream().sorted().forEach(System.out::println);
//
List<Employee> employees = EmployeeData.getEmployees();
// employees.stream().sorted((e1,e2) ->{
// return Integer.compare(e1.getAge(),e2.getAge());
// }).forEach(System.out::println);
employees.stream().sorted((e1,e2) ->Integer.compare(e1.getAge(),e2.getAge())).forEach(System.out::println);
System.out.println("--------------------------");
//年龄一样,按照薪水来比较
employees.stream().sorted((e1,e2) -> {
int result = Integer.compare(e1.getAge(), e2.getAge());
if (result != 0) {
return result;
} else {
return Double.compare(e1.getSalary(), e2.getSalary());
}
}).forEach(System.out::println);
}
}
--------------------------------------------------------------------------------------------------------------------------------------------
package StreamAPI;
import MethodTest.Employee;
import MethodTest.EmployeeData;
import org.junit.Test;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
//1.匹配与查找
//1.1 allMatch(Predicate p)——检查是否匹配所有元素
//练习:是否所有员工的年龄都大于18\
//1.2 anyMatch(Predicate p)——检查是否至少匹配一个元素
//练习:是否存在员工的工资大于10000
//1.3 noneMatch(Predicate p)——检查是否没有匹配的元素
//练习:是否不存在员工姓王
//1.4 findFirst()——返回第一个元素
//1.5 findAny()——返回当前流中的任意元素
//1.6 count()——返回流中元素的总个数
//1.7 max(Comparator c)——返回流中最大值
// 练习:返回最高的工资
//1.8 min(Comparator c)——返回流中最小值
//练习:返回最低的工资
//1.9 foreach(Consumer c)——内部迭代
public class StreamEndTest1 {
@Test
public void test1(){
List<Employee> employees = EmployeeData.getEmployees();
//1.1allMatch(Predicate p)——检查是否匹配所有元素
//练习:是否所有员工的年龄都大于18
boolean allMatch = employees.stream().allMatch(e->e.getAge()>18);
System.out.println(allMatch);
//1.2anyMatch(Predicate p)——检查是否至少匹配一个元素
//练习:是否存在员工的工资大于10000
boolean anyMatch = employees.stream().anyMatch(e->e.getSalary()>1000 );
System.out.println(anyMatch);
//1.3noneMatch(Predicate p)——检查是否没有匹配的元素
//练习:是否不存在员工姓王
boolean noneMatch = employees.stream().noneMatch(e->e.getName().startsWith("王"));
System.out.println(noneMatch);
//1.4findFirst()——返回第一个元素
Optional<Employee> first = employees.stream().findFirst();
System.out.println(first);
//1.5findAny()——返回当前流中的任意元素
Optional<Employee> any1 = employees.stream().findAny();//串行流,从第一个取
Optional<Employee> any2 = employees.parallelStream().findAny();//并行流,从任意一个取
System.out.println(any1+"\n"+any2);
}
@Test
public void test2(){
//1.6count()——返回流中元素的总个数
List<Employee> employees = EmployeeData.getEmployees();
long count = employees.stream().filter(e->e.getSalary()>5000).count();
System.out.println(count);
//1.7max(Comparator c)——返回流中最大值
//练习:返回最高的工资
Stream<Double> salaryStream = employees.stream().map(e -> e.getSalary());
Optional<Double> max1 = salaryStream.max(Double::compare);
Optional<Employee> max2 = employees.stream().max((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
System.out.println(max1+"\n"+max2);
//1.8min(Comparator c)——返回流中最小值
//练习:返回最低工资的员工
Optional<Employee> employee=employees.stream().min((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
System.out.println(employee);
Optional<Double> min = employees.stream().map(Employee::getSalary).min(Double::compare);
System.out.println(min);
//1.9forEach(Consumer c)——内部迭代
//使用方法引用
employees.stream().forEach(System.out::println);
//使用集合的遍历
employees.forEach(System.out::println);
//2.
}
//2.归约
//2.1 reduce(T identity,BinaryOpretor) 可以将流中元素反复结合起来,得到一个值,返回T
//练习:计算1-10的自然数的和
//2.2 reduce(BinaryOpretor) 可以将流中元素反复结合起来,得到一个值,返回 Optional<T>
//练习:计算公司所有员工工资的总和
@Test
public void test3(){
//2.1 reduce(T identity,BinaryOpretor) 可以将流中元素反复结合起来,得到一个值,返回
//练习:计算1-10的自然数的和
List<Integer> lsit= Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Integer sum = lsit.stream().reduce(0, Integer::sum);//Integer有个静态方法,sum传两个参数;函数式接口reduce也是传入两个参数
System.out.println(sum);
//2.2 reduce(BinaryOpretor) 可以将流中元素反复结合起来,得到一个值,返回 Optional<T>
//练习:计算公司所有员工工资的总和
List<Employee> employees = EmployeeData.getEmployees();
Stream<Double> salaryStream = employees.stream().map(Employee::getSalary);
// Optional<Double> sumMoney=salaryStream.reduce(Double::sum);
Optional<Double> sumMoney=salaryStream.reduce((d1,d2)->d1+d2);
System.out.println(sumMoney);
}
//3.收集
//collect 将流转换为其他形式,接收一个Collector接口的实现,用于给Stream中元素做汇总的方法
@Test
public void test4(){
//练习:查找工资大于6000的员工,结果返回为一个List(有序)或Set(无序)
List<Employee> employees = EmployeeData.getEmployees();
List<Employee> employeeList =employees.stream().filter(e->e.getSalary()>6000).collect(Collectors.toList());
employeeList.forEach(System.out::println);
System.out.println("---------------------------");
Set<Employee> employeeSet =employees.stream().filter(e->e.getSalary()>6000).collect(Collectors.toSet());
employeeSet.forEach(System.out::println);
}}
5.Optional类
package OptionalTest;
import org.junit.Test;
import java.util.Optional;
/**
* Optional类:用于解决空指针异常的问题,为了不出现空指针出现异常而创建的
*
* Optional.of(T t) : 创建一个 Optional 实例,t 不能为 null
* Optional.empty() : 创建一个空的 Optional 实例
* Optional.ofNullable(T t) : t 可以为 null
*/
public class OptionalTest {
@Test
public void test1(){
Girl girl= new Girl("哈哈");
// girl = null;
//of(T t) 方法必须保证t不能为空,否则报空指针异常
Optional<Girl> optionalGirl =Optional.of(girl);
System.out.println(optionalGirl);
}
@Test
public void test2(){
Girl girl= new Girl("哈哈");
// girl = null;
//ofNullable(T t) 方法t可以为空
Optional<Girl> optionalGirl =Optional.ofNullable(girl);
System.out.println(optionalGirl);
//orElse(T t1) 方法如果optionalGirl内部封装的t是非空,则返回内部的t;
// 如果内部的t为空,则返回orElse()方法中的参数t1
Girl girl1 = optionalGirl.orElse(new Girl("哈哈"));
System.out.println(girl1);
}
@Test
public void test3(){
Girl girl= new Girl("哈哈");
girl = null;
//empty() 方法创建一个空的 Optional 实例
Optional<Girl> optionalGirl =Optional.empty();
System.out.println(optionalGirl);
}
public String getGirlName1(Boy boy){
return boy.getGirl().getName();
}
@Test
public void test4(){
Boy boy = new Boy();
String girlName = getGirlName1(boy);
System.out.println(girlName);//NullPointerException
}
//优化以后
public String getGirlName2(Boy boy){
if(boy != null){
Girl girl = boy.getGirl();
if (girl !=null){
return girl.getName();
}
}
return null;
}
@Test
public void test5(){
Boy boy = new Boy();
String girlName = getGirlName2(boy);
System.out.println(girlName);//NullPointerException
}
//典型练习,保证如下的方法执行中不会出现空指针异常
//使用Optional类优化以后
public String getGirlName3(Boy boy){
Optional<Boy> optionalBoy = Optional.ofNullable(boy);
//此时boy1一定非空
Boy boy1 = optionalBoy.orElse(new Boy(new Girl("呵呵")));//orElse方法,如果为空,就返回一个默认值
Girl girl = boy1.getGirl();
Optional<Girl> girlOptional=Optional.ofNullable(girl);//不空就是本身数据
Girl girl1 = girlOptional.orElse(new Girl("嘿嘿"));//为空就是orElse()中的数据
//girl1一定非空
return girl1.getName();
}
@Test
public void test6(){
Boy boy = null;
boy = new Boy();
boy= new Boy(new Girl("嘻嘻"));
String girlName = getGirlName3(boy);
System.out.println(girlName);//哈哈
}
}
----------------------------------------------------------------------
package OptionalTest;
import org.junit.Test;
import java.util.Optional;
public class OptionalTest1 {
@Test
public void test1() {
Optional<Object> op1 = Optional.empty();
// if (op1.isPresent()){//Optional封装的数据是否为空
if (!op1.isPresent()) {//Optional封装的数据是否包含数据
System.out.println("数据为空");
}
System.out.println(op1);
System.out.println(op1.isPresent());
//如果Optional封装的数据为空,则get()报错;如果不为空,则返回参数值
// System.out.println(op1.get());
}
@Test
public void test2() {
String str = "hello";
str= null;
//Optional.ofNullable(str);//允许为空
//of(T t)方法要求传入的参数t不能为空,如果为空,会抛出NullPointerException
Optional<String> op1 = Optional.of(str);
//明确不是空使用 get() 和 of()
//get()通常与of()方法搭配,用于获取内部的封装的数据
String str1 = op1.get();
System.out.println(str1);
}
@Test
public void test3() {
//有可能为空,使用
//ofNullable和orElse
String str ="哈哈";
//ofNullable(T t)封装数据t赋给Optional内部的value,不要求t非空
// Optional<String> op1 = Optional.ofNullable(str);
Optional<String> op1 = Optional.ofNullable(null);
//orElse(T t1)方法,如果Optional封装的数据为空,则返回参数t
//value为空,则返回t1
String str1 = op1.orElse("默认值");
System.out.println(str1);
}
}