- 1.Lambda表达式
- 1.Lambda表达式和方法引用的案例
- 2.Lmabda表达式的6种形式
- 3.Lambda表达式详细实例
- 2.函数式接口
- 1.函数式接口描述
- 2.java内置四大函数式接口
- 3.方法引用与构造器
- 1.方法引用
- 2.构造器引用
- 4.Stream API
- 1.Stream API说明
- 2.stream实例化对象的四种方式
- 3.stream 中间操作
- 4.stream的终止操作
- 5.Option类
- 1.Optional的构造函数
- 2.Optional的常用函数
java8新特性:
- 速度更快
- 代码更少(新增语法:Lambda 表达式)
- 新增 Stream API
- 便于执行
- 最大化减少空指针异常:Option
- Nashorn引擎,运行在jvm中运行 java script 代码,jdk6就可以,但是jdk8做了更好的优化
例如:在java的bin目录下使用 jjs命令编译以下js代码:jjs fileName.js
print(add(5,6))
function add( a,b) {
var sum=a+b;
return a+b;
}
1.Lambda表达式
Lambda 是一个匿名函数,可以把 Lambda理解为是一段可以传递的代码(将代码像数据一样进行传递),使用它可以让我们的变的更加简洁,让java语言的表达能力得到了提升,让我们写的代码更加简短,优雅。
1.Lambda表达式和方法引用的案例import org.junit.jupiter.api.Test;
import java.util.Comparator;
public class LambadaTest {
// 使用原来的方式:new一个接口,实现匿名对象
@Test
void test1(){
Runnable runnable= new Runnable() {
@Override
public void run() {
System.out.println("hello world1");
}
};
// 使用对象调用普通方法 run(),并不是多线程的方式进行启动
runnable.run();
}
// 使用Lambda的方式
@Test
void test2(){
Runnable runnable=()->System.out.println("hello world2");
runnable.run();
}
// 原生方式
@Test
void test3(){
Comparator comparator = new Comparator() {
@Override
public int compare(Integer o1, Integer o2) {
// o1>o2: result>0 o1 comparator=(o1,o2)->Integer.compare(o1,o2);
int result = comparator.compare(20, 20);
System.out.println("result="+result);
}
// 使用方法引用
@Test
void test5(){
Comparator comparator=Integer::compare;
int result = comparator.compare(20, 20);
System.out.println("result="+result);
}
}
2.Lmabda表达式的6种形式
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.function.Consumer;
public class LambdaDemo1 {
// 1.Lambda表达式:无参无返回值
@Test
void test1(){
Runnable runnable=()->System.out.println("hello world");
runnable.run();
}
//2.Lambda表达式:有一个参数,但是没有返回值
@Test
void test2(){
// 原生方式
Consumer consumer = new Consumer() {
@Override
public void accept(String s) {
System.out.println("result="+s);
}
};
consumer.accept("admin");
System.out.println("-----------------------------");
// Lambda表达式的方式:
Consumer consumer2=(String s)->{
System.out.println("result="+s);
};
consumer2.accept("lambda");
}
// 3.Lambda表达式:数据类型可以省略,编译器推断得出 称为 “类型推断”
@Test
void test3(){
Consumer consumer=(s)->{
System.out.println("result="+s);
};
consumer.accept("hello");
ArrayList list = new ArrayList<>();//类型推断
int[] arr={1,2,3};// 类型推断
}
//4.Lambda表达式:若只需要一个参数时,参数的小括号可以省略
@Test
void test4(){
Consumer consumer= arg->{
System.out.println("result="+arg);
};
consumer.accept("hello");
}
//5.Lambda表达式:需要两个或以上的参数,执行多条语句,并且可以有返回值
@Test
void test5(){
Comparator comparator=(o1,o2)->{
int result = Integer.compare(o1, o2);
return result;
};
int result = comparator.compare(20, 15);
System.out.println("result="+result);
}
//6.Lambda表达式:当Lambda表达式只有一条语句时,return与大括号都可以省略
@Test
void test6(){
Comparator comparator = (o1,o2)->Integer.compare(o1,o2);
int result = comparator.compare(20, 52);
System.out.println("result="+result);
}
}
3.Lambda表达式详细实例
1.无参数,无返回值
@FunctionalInterface
public interface LambdaInterface{
void show();
}
class MyTest{
public static void main(String[] args) {
//1.无参无返回值写法1:至有一条语句
LambdaInterface l1=()->System.out.println("hello world");
l1.show();
System.out.println("-------------------------");
//1.无参无返回值写法1:需要执行多条语句
LambdaInterface l2=()->{
System.out.println("hello world1");
System.out.println("hello world2");
};
l2.show();
}
}
2.有一个参数但无返回值
@FunctionalInterface
public interface LambdaInterface{
void select(String id);
}
class MyTest{
public static void main(String[] args) {
// 只有一条语句
LambdaInterface l1=(String id)->System.out.println("id="+id);
// 如果是多条语句:使用{}包起来
LambdaInterface l2=(String id)->{
if (id.equals("123")){
System.out.println("查询成功");
}else {
System.out.println("查询失败");
}
};
l1.select("123");
l2.select("234");
}
}
3.数据类型可以省略,根据编译器根据编译器推断得出,称为:类型推断
@FunctionalInterface
public interface LambdaInterface{
void select(String id);
}
class MyTest{
public static void main(String[] args) {
// 只有一条语句(在上一个基础的例子上去掉了数据类型)
LambdaInterface l1=( id)->System.out.println("id="+id);
// 如果是多条语句:使用{}包起来(在上一个基础的例子上去掉了数据类型)
LambdaInterface l2=( id)->{
if (id.equals("123")){
System.out.println("查询成功");
}else {
System.out.println("查询失败");
}
};
l1.select("123");
l2.select("234");
}
}
4.若只需要一个参数时,-> 左边小括号可省略(多个参数则不可省)
@FunctionalInterface
public interface LambdaInterface{
void select(String id);
}
class MyTest{
public static void main(String[] args) {
// 只有一条语句(在上一个基础的例子上去掉了小括号)
LambdaInterface l1 = id ->System.out.println("id="+id);
// 如果是多条语句:使用{}包起来((在上一个基础的例子上去掉了小括号)
LambdaInterface l2 = id->{
if (id.equals("123")){
System.out.println("查询成功");
}else {
System.out.println("查询失败");
}
};
l1.select("123");
l2.select("234");
}
}
5.需要多个参数,有返回值,并且需要执行多行代码
@FunctionalInterface
public interface LambdaInterface{
String login(String username,String password);
}
class MyTest{
public static void main(String[] args) {
LambdaInterface l = (username,password)->{
if ("admin".equals(username)&&"123".equals(password))return " login success";
return "login fail";
};
String result = l.login("admin", "123");
System.out.println("result="+result);
}
}
6.当Lambda表达式只有一条语句时,return与大括号都可以省略
@FunctionalInterface
public interface LambdaInterface{
String login(String username,String password);
}
class MyTest{
public static void main(String[] args) {
LambdaInterface l = (username,password)->username.equals("admin")&&password.equals("123")?" success":" fail";
String result = l.login("admin", "123");
System.out.println("result="+result);
}
}
2.函数式接口
1.函数式接口描述
1.只包含一个抽象方法的接口称之为:函数式接口
2.你可以使用Lambda表达式来创建该接口的实例对象,(若Lambda表达式抛出一个受检异常(即:非运行时异常),那么该异常需要在模板接口的方法上进行声明)
3.我们可以在接口上使用 @FunctionalInterface注解,这样可以检测该接口是否是一个函数式接口,加上了该注解,就意味着该接口只能有一个抽象方法,如果有多个会抛出编译时异常,即使不加该注解,只有一个接口中只定义了一个抽象方法,该接口依旧是函数式接口,@FunctionalInterface 注解只是帮我们在编译时检测该接口是否满足函数式接口的要求。
4.在 java.util.function下定义了 java8 丰富的函数式接口,Lambda的本质就是函数式接口的一个实例对象
2.java内置四大函数式接口四大函数式接口指的是Consumer、Function、Predicate、Supplier 位于java.util.function包下
第一种:Consumer:消费型接口(传递一个对象,进行消费,不返回非任何结果)void accept(T t);
第二种:Supplier:供给型接口 (不传递任何参数,给你返回一个对象) T get();
第三种:Function
第四种:Predicate:断言型接口(传递一个对象,进行判断,返回判断的结果) boolean test(T t)
实例:
public class FunctionInterface {
@Test
void test1(){
List list = Arrays.asList("北京", "南京", "东京", "重庆", "四川", "深圳");
List result = filterString(list, arg -> arg.contains("京"));
System.out.println(result);
}
public static List filterString(List list , Predicate predicate){
List filter = new ArrayList<>();
for (String value:list){
// 如果满足规则就加入到一个新的集合中
if (predicate.test(value)) filter.add(value);
}
return filter;
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u1Izktrm-1635059552943)(C:Users14823AppDataRoamingTyporatypora-user-imagesimage-20211021233411179.png)]
3.方法引用与构造器 1.方法引用1.当要传递的Lambda表体操作,已经有具体实现方法的时候,可以直接使用方法引用
2.方法引用可以看做是Lambda表达式深层次的表达,方法引用就是Lambda表达式,也就是函数式接口的实例,通过方法的名字来指向一个方法。
3.要求:实现抽象接口的方法的参数列表和返回值,必须与方法引用的方法参数列表和返回值保持一致。
4.使用格式:使用操作符 :: 将类或者方法名分开。
- 对象 :: 实例方法
- 类 :: 静态方法名
- 类 :: 实例方法名
1.对象 :: 实例方法
class FunctionQuoteImpl{
public void show(String args){
System.out.println(args);
}
public static FunctionQuoteImpl newInstance(){
return new FunctionQuoteImpl();
}
}
class MyTest2{
@Test
void test1(){
// Lambda 表达式
Consumer consumer1 = s -> System.out.println(s);
consumer1.accept("hello1");
// 方法引用:要求接口中的抽象方法的形参列表和返回值,与方法引用的方法的形参列表和返回值都相同 对象::实例方法
Consumer consumer2 = System.out::println;
consumer2.accept("hello2");
// 自定义
Consumer consumer3 = FunctionQuoteImpl.newInstance()::show;
consumer3.accept("hello3");
}
}
2.类 :: 静态方法名
class FunctionQuoteImpl{
// 自定义:类::静态方法
public static Integer compare(int a,int b){
//比较两个数的大小
return a-b>0?1:a-b<0?-1:0;
}
}
class MyTest2{
@Test
void test2(){
// Lambda表达式
Comparator compare1=((o1, o2) -> Integer.compare(o1,o2));
int result1 = compare1.compare(20, 10);
System.out.println("result1="+result1);
// 方法引用:要求接口中的抽象方法的形参列表和返回值,与方法引用的方法的形参列表和返回值都相同 类::静态方法
Comparator compare2=Integer::compare;
int result2 = compare1.compare(20, 10);
System.out.println("result2="+result2);
//自定义
Comparator compare3 = FunctionQuoteImpl::compare;
int result3 = compare3.compare(5, 5);
System.out.println("result3="+result3);
}
}
3.类 :: 实例方法名
@Test
void test3(){
// 1.
// Lambda表达式
BiPredicate b1=(x, y)->x.equals(y);
System.out.println(b1.test("a","b"));//结果:false
// 方法引用: 类::实例方法
BiPredicate b2=String::equals;
System.out.println(b2.test("a","b"));//结果:false
System.out.println("-------------------------------------------");
//2.
// Lambda表达式
Comparator comparator=(o1,o2)->o1.compareTo(o2);
int result0 = comparator.compare("ad", "ae");
System.out.println("result0="+result0);
// 方法引用: 类::实例方法
Comparator compare = String::compareTo;
int result1 = compare.compare("ad", "ae");
System.out.println("result1="+result1);
System.out.println("-------------------------------------------");
//3.
// Lambda表达式
Function function1 = e->e.getMessage();
String result2 = function1.apply(FunctionQuoteImpl.newInstance());
System.out.println("result2="+result2);
// 方法引用: 类::实例方法
Function message = FunctionQuoteImpl::getMessage;
String result3 = message.apply(FunctionQuoteImpl.newInstance());
System.out.println("result3="+result3);
}
2.构造器引用
构造器引用和方法引用都是Lambda表达式的升级表达方式,而Lmabda表达式是函数式接口的一个实例对象,那么也就是说构造器引用和方法引用也都是函数式接口的一个实例对象。
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
public class ConstructorQuote {
@Test
void test1(){
// Lambda的写法
Supplier supplier1 = ()->new User();
System.out.println("lambda="+supplier1.get() );
// 构造器引用
Supplier supplier2= User::new ;
System.out.println("构造器引用="+supplier2.get() );
}
@Test
void test2(){
Function function = id->new User(id);
System.out.println("lambda="+ function.apply(20));
Function function2 = User::new;
System.out.println("构造器引用="+function2.apply(30));
}
@Test
void test3(){
BiFunction function1=(id,name)->new User(id,name);
System.out.println("lambda="+function1.apply(10,"张三"));
BiFunction function2 = User::new;
System.out.println("构造器引用="+function1.apply(20,"李四"));
}
// 数组引用
@Test
void test4(){
Function arr1 = length->new String[length];
System.out.println("arr1="+Arrays.toString(arr1.apply(5)));
Function arr2 = String[]::new;
System.out.println("arr2="+Arrays.toString(arr1.apply(10)));
}
}
class User{
private int id;
private String name;
private int status;
public User(){
}
public User(int id){
this.id=id;
}
public User(int id,String name,int status){
this.id=id;
this.name=name;
this.status=status;
}
public User(int id,String name){
this.id=id;
this.name=name;
}
4.Stream API
1.Stream API说明
- java 8中有两大极为重大的改变,Lambda表达式和Stream API
- Stream API (java.util.stream)把真正的函数式编程风格引入到java中,这是目前对java类库最好的补充,因为Stream API可以极大的提升java程序员的生产力,让程序员写出更加简洁,高效的代码。
- Stream 是java8中集合的关键抽象概念,可以对集合中的数据进行复杂的查询,过滤,映射数据库操作等。使用Stream API 对集合中的数据进行操作,就类似于使用SQL执行的数据库查询,也可以使用Stream API来进行操作,简单来说就是Stream API 提供一种高效且易于处理集合中的数据的一种方式。
- Stream API 和Collection集合的区别:Collection是静态的内存数据结构,而Stream 是有关于计算的,前者是面向内存,后者面向cpu,通过cpu实现计算。
注意:
- stream 本身不会存储元素
- stream 不会改变原来的对象,相反,返回一个持有新结果的stream
- stream 操作是懒加载延迟的,意味着需要等到终止操作获取结果的时候才会去执行,不会被再次使用
User类
package java8new.stream;
import java.util.ArrayList;
import java.util.List;
public class User {
private int id;
private int age;
private String name;
public static List getUserList(){
List userList = new ArrayList<>();
userList.add(new User(1,20,"小明"));
userList.add(new User(2,21,"小王"));
userList.add(new User(3,22,"小李"));
userList.add(new User(4,23,"小华"));
userList.add(new User(5,24,"小花"));
userList.add(new User(6,25,"小浪"));
return userList;
}
public User(int id, int age, String name) {
this.id = id;
this.age = age;
this.name = name;
}
public User() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", age=" + age +
", name='" + name + ''' +
'}';
}
}
1.使用集合的stream方法
ListuserList = User.getUserList(); // 返回一个顺序流 Stream stream = userList.stream(); // 并行流 Stream userStream = userList.parallelStream();
2.使用数组的方式
int[] arr={1,2,3,4,5,6};
// 能够处理对应基本数据类型的数组 ,还支持自定义类型数组
IntStream stream = Arrays.stream(arr);
3.通过stream 本身的静态方法 of()
// 实际调用的还是: Arrays.stream(values) Streamstream = Stream.of(1, 2, 3, 4, 5, 6);
4.创建无限流
// 迭代 ,案例:生成前10个偶数 Stream.iterate(0, t -> t + 2).limit(10).forEach(System.out::println); // 生成 ,案例:生成10个随机数 Stream.generate(Math::random).limit(10).forEach(System.out::println);3.stream 中间操作
1.切片与筛选
Stream filter(Predicate super T> predicate): 接收Lambda表达式,才从流中排除某些元素
Stream distinct(): 筛选,通过流生成的hashCode和equals去除重复的元素
Stream limit(long maxSize): 截断流,使其元素不超过指定的数量
Stream skip(long n): 跳过元素,返回一个扔掉前n个元素的流,若流中元素不足n个,则返回一个空流,与limt互补
@Test
void test1(){
List userList = User.getUserList();
//userList.stream().filter(user -> user.getId() < 3).forEach(System.out::println);
//userList.stream().limit(3).forEach(System.out::println);
//userList.stream().skip(3).forEach(System.out::println);
User admin = new User(7, 27, "admin");
userList.add(admin);
userList.add(admin);
userList.add(admin);
userList.forEach(System.out::println);
System.out.println("-----------------------------------");
userList.stream().distinct().forEach(System.out::println);
}
2.映射
@Test
void test2(){
// 将集合中的所有字母转换为大写
List stringList = Arrays.asList("a,b,c,d");
stringList.stream().map(s->s.toUpperCase()).forEach(System.out::println);
List list = Arrays.asList("aa","bb","cc");
// map的方式
Stream> stream = list.stream().map(StreamDemo2::formStringToStream);
stream.forEach(s->{s.forEach(System.out::println);});
System.out.println("---------------");
// flatMap的方式 如果是集合中套用集合的方式,优先使用 flatMap的方式
Stream stream2 = list.stream().flatMap(StreamDemo2::formStringToStream);
stream2.forEach(System.out::println);
}
public static Stream formStringToStream(String str){
ArrayList list = new ArrayList<>();
char[] charArray = str.toCharArray();
for (Character value:charArray){
list.add(value);
}
return list.stream();
}
3.排序
我们先来看下Comparable 和Comparator的区别
在java中Integer,Double 等基本数据类型和Sting都实现了Comparable接口,不用我们在自己去实现,需要比较他们的大小时,直接调用compareTo方法即可。对于类的比较,需要我们定义比较用到的字段比较逻辑。Comparable是内部比较器需要在类内部实现,Comparator是外部比较器生成比较器对象,就比如说在在List集合中对集合中的对象进行比较,那么我们就需要实现Comparator接口,并且实现compare方法自定义排序规则。
Comparable 和Comparator案例:
package java8new.stream; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; public class User implements Comparable, Comparator { private int id; private int age; private String name; private String sex; public static List getUserList(){ List userList = new ArrayList<>(); userList.add(new User(1,29,"小明","男")); userList.add(new User(2,21,"小王","男")); userList.add(new User(3,18,"小李","女")); userList.add(new User(4,23,"小华","女")); userList.add(new User(7,50,"小花","女")); userList.add(new User(5,50,"小k","男")); userList.add(new User(6,60,"小浪","女")); return userList; } public User(int id, int age, String name,String sex) { this.id = id; this.age = age; this.name = name; this.sex=sex; } public User(int id, int age, String name) { this.id = id; this.age = age; this.name = name; } public User() { } public String getSex() { return sex; } public void setSex(int id) { this.sex = sex; } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "User{" + "id=" + id + ", age=" + age + ", name='" + name + ''' + '}'; } // 内部比较器 public int compareTo(User o) { return Integer.compare(this.getAge(),o.getAge()); } // 外部比较器 public int compare(User o1, User o2) { return Integer.compare(o1.getAge(),o2.getAge() ); } public static User getMax(User o1,User o2){ User result = o1.compareTo(o2)>=0? o1: o2; return result; } public static void main(String[] args) { User user1 = new User(9, 50, "小X", "男"); User user2 = new User(8, 20, "小Y", "女"); List userList = User.getUserList(); // 内部排序,自定义比较两个对象的大小 实现Comparable接口并且实现compareTo方法 int compareResult = user1.compareTo(user2); System.out.println("compareResult="+compareResult); System.out.println("比较结果="+getMax(user1,user2)); System.out.println("-----------------------"); // 使用Steam流对集合中的数据进行自定义排序,实现Comparator的compare方法按照自定义规则排序 userList.stream().sorted(((o1, o2) ->Integer.compare(o1.getAge(),o2.getAge()))).forEach(System.out::println); // 外部排序使用,使用Collections的sort方法,User类需要实现Comparator的compare方法实现自定义排序 Collections.sort(userList); System.out.println("-----------------------"); userList.forEach(System.out::println); } }
stream流式排序
List4.stream的终止操作userList = new ArrayList<>(); userList.add(new User(1,29,"小明")); userList.add(new User(2,21,"小王")); userList.add(new User(3,18,"小李")); userList.add(new User(4,23,"小华")); userList.add(new User(7,50,"小花")); userList.add(new User(5,50,"小k")); userList.add(new User(6,25,"小浪")); return userList; } @Test void test3(){ List list = Arrays.asList(12, 62, 5, 14, 30, 45); // sorted():自然排序 list.stream().sorted(); System.out.println(list); System.out.println("-----------------------------"); // sorted(Comparator com): 定制排序 根据user对象的age属性进行排序 List userList = User.getUserList(); //userList.stream().sorted((e1,e2)->Integer.compare(e1.getAge(),e2.getAge())).forEach(System.out::println); // 如果两人的年龄一样就根据id来继续排序(从小大到) userList.stream().sorted((e1,e2)->{ int differencevalue = Integer.compare(e1.getAge(), e2.getAge()); if (differencevalue!=0){ return differencevalue; }else { return Integer.compare(e1.getId(),e2.getId()); //如果想从大到小,在返回的值前添加个 负号即可 } }).forEach(System.out::println); }
1.匹配与查找
import org.junit.jupiter.api.Test;
import java.util.List;
import java.util.Optional;
public class StreamDemo3 {
@Test // boolean allMatch(Predicate p):检查是否匹配所有的元素
void test1(){
List userList = User.getUserList();
// 判断userList集合中的用户的年龄都是否大于18岁,是返回 true ,不是返回false
boolean isAgeLegal = userList.stream().allMatch(s -> s.getId() > 0);
System.out.println(isAgeLegal);
}
@Test // boolean anyMatch(predicate p) :检查是否至少有一个元素匹配
void test2(){
List userList = User.getUserList();
// 检查userList集合中的用户是否 至少有一个人的年龄=20
boolean isAgeLegal = userList.stream().anyMatch(s -> s.getAge() == 20);
System.out.println(isAgeLegal);
}
@Test //noneMatch(Predicate p) : 检查是否没有匹配的元素
void test3(){
List userList = User.getUserList();
// 检查userList中 是否 name结尾没有"浪"的用户 ,如果集合中有一个用户的名字是以 浪 结尾的则返回false
boolean b = userList.stream().noneMatch(s -> s.getName().endsWith("浪"));
System.out.println(b);
}
@Test // findFirst() :返回第一个元素
void test4(){
// 对userList集合中的元素按照id进行排序,然后取出第一个元素
Optional first = User.getUserList().stream().sorted((e1, e2) -> Integer.compare(e1.getId(), e2.getId())).findFirst();
User user = first.get();
System.out.println(user);
}
@Test //findAny() :返回当前流中的任意元素
void test5(){
List userList = User.getUserList();
// 返回userList集合中的一个任意元素,
Optional any = userList.stream().findAny();
System.out.println(any.get());
}
@Test // count():返回流中元素的个数
void test6(){
List userList = User.getUserList();
// 统计UserList集合中有多少个用户
long count = userList.stream().count();
System.out.println("count="+count);
}
@Test //max(Comparator c) :返回流中最大值
void test7(){
List userList = User.getUserList();
// 返回userList集合中年龄最大的用户
Optional user = userList.stream().max((e1, e2) -> Integer.compare(e1.getAge(), e2.getAge()));
System.out.println("user="+user);
}
@Test //min(Comparator c) : 返回流中最小值
void test8(){
List userList = User.getUserList();
// 返回userList集合中年龄最小的用户
Optional user = userList.stream().min((e1, e2) -> Integer.compare(e1.getAge(), e2.getAge()));
System.out.println("user="+user);
}
@Test // forEach(Consumer c) :内部迭代
void test9(){
List userList = User.getUserList();
// 遍历userList中所有的用户,获取到他们的名字
userList.stream().forEach(s-> System.out.println(s.getName()));
}
}
2.归约
// 归约
@Test
void test10(){
// T reduce(T identity, BinaryOperator accumulator)
// 求1-10自然数的和
List list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Integer sum = list.stream().reduce(0, Integer::sum);
System.out.println("sum="+sum);
// Optional reduce(BinaryOperator accumulator)
// 得到所有用户的年龄,然后再对用户的年龄进行求和
List userList = User.getUserList();
Optional ageSum = userList.stream().map(User::getAge).reduce(Integer::sum);
System.out.println("ageSum="+ageSum.get());
}
3.收集
collect() : 将流转换为其他形式,接收一个Collector接口的实现,用于给Stream中的元素做汇总
Collector接口中的实现方法决定了,如何对流的收集操作(如收集到:List,Map,Set)
@Test // 收集: collect() :将流转换为其他形式,接收一个Collector接口的实现,用于给Stream中的元素做汇总
void test11(){
List userList = User.getUserList();
// 对过滤出userList中id大于3的元素,然后放入到一个新的List集合中去
List users = userList.stream().filter(s->s.getId()>3).collect(Collectors.toList());
users.forEach(System.out::println);
System.out.println("------------------------------");
// 对过滤出userList中id大于3的元素,然后放入到一个新的Set集合中去
Set set = userList.stream().filter(s -> s.getId() > 3).collect(Collectors.toSet());
set.forEach(System.out::println);
System.out.println("------------------------------");
// 对过滤出userList中id大于3的元素,然后放入到一个新的Map集合中去
Map userMap = userList.stream().filter(s -> s.getAge() > 20).collect(Collectors.toMap(User::getId, User::getName));
userMap.forEach((key, value) -> {
System.out.println("key="+key+","+"value="+value);
});
}
@Test // 分组
void test12(){
List userList = User.getUserList();
// 将userList中按照年龄进行分组,大于20的为一组,小于20的为一组,满足条件的key为true,不满足条件的key为false,筛选出来的数据被放入的List集合中
Map> map = userList.stream().collect(Collectors.partitioningBy(value -> value.getAge() > 20));
System.out.println("partitioningBy="+map);
System.out.println("------------------------------");
// 将userList集合中的数据按照性别进行分组,分成一个map集合,key为男的对应一组List集合,key为女的对应一组List集合
Map> userMap = userList.stream().collect(Collectors.groupingBy(User::getSex));
System.out.println("groupingBy="+userMap);
}
@Test // 统计
void test13(){
List userList = User.getUserList();
// 统计出userList集合中所有用户的平均年龄
Double avgAge = userList.stream().collect(Collectors.averagingInt(User::getAge));
System.out.println("avgAge="+avgAge);
System.out.println("------------------------------");
// 统计出userList集合中的用户总数
Long userCount = User.getUserList().stream().collect(Collectors.counting());
System.out.println("userCount="+userCount);
System.out.println("------------------------------");
// 统计出userList集合中所有用户的最高年龄
Optional maxAge = User.getUserList().stream().map(User::getAge).collect(Collectors.maxBy(Integer::compare));
System.out.println("用户的最高年龄="+maxAge.get());
System.out.println("------------------------------");
// 统计出userList集合中所有用户的最低年龄
Optional minAge = User.getUserList().stream().map(User::getAge).collect(Collectors.minBy(Integer::compare));
System.out.println("用户的最低年龄="+minAge.get());
}
@Test // 连接
void test14(){
// 获取到userList集合中的所有用户的名称,然后进行直接拼接为一个字符串
String userNames1 = User.getUserList().stream().map(User::getName).collect(Collectors.joining());
System.out.println("userNames1="+userNames1); // [小明小王小李小华小花小k小浪]
// 获取到userList集合中的所有用户的名称,然后按照自定义的分割方式拼接为一个新的字符串
String userNames2 = User.getUserList().stream().map(User::getName).collect(Collectors.joining(","));
System.out.println("userNames2="+userNames2); //[小明,小王,小李,小华,小花,小k,小浪]
}
5.Option类
Optional用处:
Optional 是一个包含有可选值的包装类,里面有个泛型的vlaue,这就意味着value可以是任何引用类型的数据,这意味着 Optional 类既可以含有对象也可以为空。 当我们在使用对象调用方法的时候,如果不进行非空判断,那么则容易出现 NullPointerException
Order order = new Order(1, new Date(), 20f); Costumer costumer = new Costumer(null, 1, "小明", 1); double price = costumer.getOrder().getPrice();
这里如果我们不进行非空判断,那么就会出现空指针异常,costumer,和 order对象都可能为空,如果我们每次在调用之前都进行判断,那么代码将会复制很多,重复的代码要写很多次,如果我们的引用对象嵌套很深,那么我们的判断会变的更加的冗余。
Order order=null;
Costumer costumer=null;
if (costumer!=null){
Order order1 = costumer.getOrder();
if (order!=null){
double price = order1.getPrice();
System.out.println("price="+price);
}
}
作为一个合格的程序员,我们时刻要想着空指针异常,一出戏异常我们的程序就会异常终止,因为这个对象有可能,未被实例化,就用来调用该实例的方法,这里我们就需要判断两次,然后再去调用对应的方法,显得非常的麻烦,而Optional类的出现,就是为了解决这种尴尬的情况。
1.Optional的构造函数Optional 的三种构造方式:Optional.of(obj), Optional.ofNullable(obj) ,Optional.empty()
- Optional.of(obj):它要求传入的 object不能是 null 值的, 否则直接报NullPointerException 异常。
Optionaloptional = Optional.of(costumer); // 如果传递的是null将会抛出空指针异常 System.out.println(optional.get());
- Optional.ofNullable(obj):如果传递进来的对象,那么就调用 empty() 创建一个空的Optional对象,如果不为空那么就调用 Optional.of(obj)
Optionalcostumer2 = Optional.ofNullable(null);//即使传递是空也不会出现空指针异常
- Optional.empty():返回一个空的 Optional 对象
Optional2.Optional的常用函数
public boolean isPresent():如果 Optional 内部的value(value就是我们初始化Optional 对象传递进去的 object )为空返回false,不为空返回true
//如果 Optional 内部的value为空返回false,不为空返回true boolean present = empty.isPresent();
public void ifPresent(Consumer super T> consumer) : 接收一个Consumer接口的实例对象,如果Optional中的value不为空就执行Consumer实例中的方法,如果为空就什么也不做
// 接收一个Consumer接口的实例对象,如果Optional中的value不为空就执行Consumer实例中的方法,如果为空就什么也不做
optional.ifPresent(consumer->System.out.println("optional value is not null")); //如果optional是null 将无任何输出
public T get():如果 Option中的value不为空就进行返回,如果为空就抛出空指针异常
// 如果 Option中的value不为空就进行返回,如果为空就抛出空指针异常
Costumer cos = optional1.get();
System.out.println("cos="+cos);
public T orElse(T other) : 如果 Optional 中的value不为空,那么就返回原本的value,如果为空那么久使用我们自定义的object
// 如果 Optional 中的value不为空,那么就返回原本的value,如果为空那么久使用我们自定义的object
Object costumer3 = (Costumer)empty.orElse(new Costumer(order, 1, "小明", 1));
System.out.println(costumer3);
public T orElseGet(Supplier extends T> other) : 如果 Optional 中的value不为空,那么就返回原本的value,如果为空那么久使用我们自定义的object(区别是参数需要是Supplier 接口的实现类)
//如果 Optional 中的value不为空,那么就返回原本的value
//如果为空那么久使用我们自定义的object(区别是参数需要是Supplier接口的实现类)
Costumer cos1 = optional1.orElseGet(()->new Costumer()); // lambda表达式
Costumer cos2 = optional1.orElseGet(Costumer::new); // 构造器引用
Costumer cos3 = optional1.orElseGet(new Supplier() { // 匿名内部类
@Override
public Costumer get() {
return new Costumer();
}
});
public T orElseThrow(Supplier extends X> exceptionSupplier) throws X :如果 Optional 中的value不为空,那么就返回原本的value,否则抛出supplier接口创建的异常
//如果 Optional 中的value不为空,那么就返回原本的value,否则抛出supplier接口创建的异常
Costumer cos4 = optional1.orElseThrow(()->new RuntimeException("orElseThrow 出现异常"));
public Optional filter(Predicate super T> predicate) :如果 Optional中的value不为空并且满足断言条件,则返回 value,否则返回一个空的 Option
// 如果 Optional中的不为空并且满足断言条件,则返回 value,否则返回一个空的 Option
Optional cos4 = optional1.filter(s -> s.getOrder().getId() == 1);
System.out.println("cos4="+cos4.get());
map和flatMap
Optional optionalOrder = Optional.ofNullable(order);
//如果有值,则对其执行调用mapping函数得到返回值。如果返回值不为null,则创建包含mapping返回值的Optional作为map方法返回值,否则返回空Optional
Optional date = optionalOrder.map(Order::getTime);
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date.get()));
// 如果有值,为其执行mapping函数返回Optional类型返回值,否则返回空Optional。
Optional costumerOptional = Optional.ofNullable(costumer);
Optional costumerName = costumerOptional.flatMap(OptionalDemo::getCustomerName);
System.out.println("costumerName="+costumerName.get());



