Predicate是个函数式接口,和Function接口一样,不同的是Predicate接口的定义为Predicate
根据函数式接口的规定,只能有一个抽象方法,Predicate接口总共有三个主要的方法,一个抽象方法test和两个default方法and和or。
boolean test(T t);
用于检测实现类中的语句是true或false
default Predicate
连接两个Predicate
default Predicate
连接两个Predicate
比如下面的代码用于检测Student对象的年龄是否大于2
public static void main(String[] args) {
Student stu = new Student("A", 3);
System.out.println(testPredicate(stu, s -> s.getAge() > 2));
}
public static boolean testPredicate(T t, Predicate predicate) {
return predicate.test(t);
}
Predicate接口一般和Stream的filter方法结合使用,用来过滤集合中的元素。
Stream是java8基于函数式编程而出现的用于集合复杂操作的工具类,Stream的中文翻译是流、流式。字面感觉和java的IO很像,但其实没有任何的关联。Stream是以一种流式处理的思想对集合的元素进行处理。
Stream的出现基于著名的大数据并行处理思想MapReduce,MapReduce思想最早由谷歌公司提出,用来解决其搜索性能问题,后来发展成为一种通用的大数据并行处理思想。MapReduce是基于函数式编程中的Map函数和Reduce函数得来,Map函数对待处理的数据进行遍历处理,Reduce函数对Map之后的数据进行迭代式处理。
举个例子:如果有一堆数据,里面包含整型、浮点型甚至字符串,现在要求对其中的整型进行求和,显然必须先对数据遍历处理,过滤或者转换的方式得到整型,然后对得到的整型数据进行迭代式的求和。这其中的前半部分就是Map函数所做的事,后半部分就是Reduce函数做的事。
简而言之一句话:Map是对数据遍历得到想要的数据,Reduce对想要的数据进行处理得到最终想要的结果。
要了解Stream,先看下面一部分代码:
public static void main(String[] args) {
List stuList = new ArrayList<>();
stuList.add(new Student("A", 1));
stuList.add(new Student("B", 3));
stuList.add(new Student("C", 2));
stuList.add(new Student("D", 4));
List stuNameList = stuList
.stream()
.filter(stu ->stu.getAge() > 1)
.sorted((stu1, stu2) -> stu1.getAge() - stu2.getAge())
.map(stu->stu.getName())
.collect(Collectors.toList());
System.out.println(JSON.toJSONString(stuNameList));
}
上面这段代码的最终输出结果是
["C","B","D"]
整段代码的含义是从给定的学生列表stuList中,筛选出age大于1的学生,并且按照学生的age升序排列,最后得到学生name的集合。
在java8出现Stream之前,我们要实现上面的功能,一行代码肯定解决不了。这就是Stream的强大之处。
上面的代码主要涉及下面几个方法:
从对上面几个方法的简单讲解,结合Steam的MapReduce思想,Stream的方法或者Stream的处理流程总共分为3部分。
值得注意的是Stream在调用终止方法之前,不会立即执行stream中的处理方法,也就是所有对Stream的处理操作都会延迟到最终的终止方法调用时再执行。这一点和Spark很像,spark框架是一种并行的大数据处理框架,其核心思想是RDD(弹性分布式数据集),每个rdd支持两种操作Transformation和action,所有的变换在最终的action之前都不会立即执行,而是在action之时再执行。因此只要没有调用最终的终止方法,Stream所属对象的集合可以进行增删改的操作
Stream常用的获取方式有两种,Stream静态方法(java8接口支持静态方法)和Collection中的stream()方法。Stream的静态方法包含两个:
of(T t)
返回一个只有一个元素的Stream
of(T... values)
返回一个包含values的Stream
如下我代码我们希望从给定的字符串数组中过滤出包含字母b的元素,并将b替换为B
String[] sarray = { "abc", "bcd", "cde" };
List sList = Stream.of(sarray)
.filter(s ->s.contains("b"))
.map(s -> s.replace("b", "B"))
.collect(Collectors.toList());
System.out.println(JSON.toJSONString(sList));
静态方法一般用来处理非集合的数据源很方便,避免将数组先转换为集合的困扰。
Collection接口定义了stream()方法,用来获取集合的流对象,根据对java8接口增强的了解,这个方法肯定是default方法。
Stream中元素的处理就是MapReduce思想中的Map过程(此Map并不等同于stream中的map方法),处理之后会得到一个新的Stream。Stream中对元素的处理方法很多,除了前面提到的最常用的filter、map、sorted之外,还有如下几个重要方法:
distinct() 无参数,过滤Stream中的重复元素,得到是无重复元素的Stream,重复元素的依据是元素的equals方法
peek(Consumer) peek接收的参数为Consumer类型,Consumer在之前讲到过接收一个T类型参数,无返回值,这是peek方法和map方法的主要区别,peek用来处理无返回值的操作,比如打印元素,而map用来处理有返回值的操作。
sorted() 和上面的带参数的sorted一样,只不过这个无参数,按照对象自定义的Comparator接口实现。如果对象未实现Comparator接口会报错。
skip(long) 跳过Stream中的前n个元素,如果Stream元素个数小于n,返回空的stream
limit(long) 获取Stream中的前n个元素,如果Stream元素个数小于n,返回全部元素
Stream的终结就是MapReduce思想中的Reduce过程(此Reduce也不等同于Stream中的reduce方法),Stream的常用终结方法除上面提到的collect方法之外,还包括以下几种:
Optional提供了一种安全的获取值的方式,避免之前为了防止出现NPE而进行繁琐的检查的工作。Optional有很多方法,常用的方法或者组合使用方式为:
组合方式:一般对一个方法的返回值使用Optional包装,然后使用ifPresent执行不为空的操作,或者使用orElseGet方法获取方法的返回值或者默认值。
System.out.println(Optional.ofNullable(null).orElseGet(() -> {
return "NULL";
}));//输出NULL
System.out.println(Optional.ofNullable("ss").orElseGet(() -> {
return "NULL";
}));//输出ss
Optional.ofNullable(null).ifPresent(System.out::println);//无输出
Optional.ofNullable("sss").ifPresent(System.out::println);//输出sss
Stream的collect方法接收一个Collector对象,Collector的官方解释是对Stream的可变减少操作。不太理解这里的可变减少是什么含义。
Collector主要有两方面的能力:
这是Collector最常见的用法,常见的操作是将Stream中的元素转为List,Set或者Map,而这三者在Collector对应的工具类Collectors中都有具体的方法可用:
Collectors.toList(),Collectors.toSet(),Collectors.toMap(Function key,Function value)
除了转List和Set不需要参数之外,转Map的方法接收两个Function函数,用来决定key和value如何生成。
下面的代码演示了如何将stuList中满足年龄大于1的学生收集到List,Set以及按照name对应stu转成Map
List stuList = new ArrayList<>();
stuList.add(new Student("B", 1));
stuList.add(new Student("A", 3));
stuList.add(new Student("A", 3));
stuList.add(new Student("C", 2));
stuList.add(new Student("D", 4));
List stuFilterList =
stuList.stream()
.filter(stu ->stu.getAge() > 1)
.collect(Collectors.toList());
System.out.println(JSON.toJSONString(stuFilterList));
Set stuFilterSet =
stuList.stream()
.filter(stu ->stu.getAge() > 1)
.collect(Collectors.toSet());
System.out.println(JSON.toJSONString(stuFilterSet));
Map stuFilterMap =
stuList.stream()
.filter(stu -> stu.getAge() > 1)
.collect(Collectors.toMap(stu -> stu.getAge(), stu -> stu));
System.out.println(JSON.toJSONString(stuFilterMap));
上面的代码运行结果为:
[{"age":3,"name":"A"},{"age":3,"name":"A"},{"age":2,"name":"C"},{"age":4,"name":"D"}]
[{"age":4,"name":"D"},{"age":2,"name":"C"},{"age":3,"name":"A"}]
Exception in thread "main" java.lang.IllegalStateException: Duplicate key
com.zong.test.Student@45f......
转List和Set都得到了我们预期的结果,Set中也对元素做了去重(Student类重写了hashcode和equals方法),但是转Map却抛出了Key重复的异常,原因是因为我们使用age作为可以,而其中有两个元素的age都为3,因此出现异常。在绝大数的使用场景下,这种情况很普遍,因此Collectors还额外提供了支持处理重复key的toMap方法
toMap(Function key,Function value,BinaryOperator mergeFunction)
三个参数中,前两个参数和之前的toMap方法含义一样,定义了获取key和value的方式,第三个参数定义了当有重复key的时候应当做的操作。上面的代码我们修改成如下即可:
Map stuFilterMap =
stuList.stream()
.filter(stu -> stu.getAge() > 1)
.collect(Collectors.toMap(stu -> stu.getAge(), stu -> stu, (stu1, stu2) -> stu2));
System.out.println(JSON.toJSONString(stuFilterMap));
其中的 (stu1, stu2) -> stu2 表示当遇到重复元素时保留新的值,我们如果希望当遇到重复的key时判断name的长度,name较长的保留,则可以写成下面的方式:
Map stuFilterMap =
stuList.stream()
.filter(stu -> stu.getAge() > 1)
.collect(Collectors.toMap(stu -> stu.getAge(), stu -> stu,
(stu1, stu2) -> stu1.getName().length() > stu2.getName().length() ? stu1 : stu2));
System.out.println(JSON.toJSONString(stuFilterMap));
Collector的另一个功能是对Stream中的元素进行分组,在Collectors中同样提供对应的方法,常用的分组方法有两个。
partitioningBy(Predicate)
接收一个Predicate对象,按照元素在Predicate中的结果分为true和false两部分
groupingBy(Function)
接收一个Function函数,分组的结果是根据Function函数的输出结果作为key,不同的元素在Function函数中的输出结果相同的在同一个key下
下面代码分别演示两个函数的使用。
List stuList = new ArrayList<>();
stuList.add(new Student("B", 1));
stuList.add(new Student("A", 3));
stuList.add(new Student("E", 3));
stuList.add(new Student("C", 2));
stuList.add(new Student("D", 4));
// 我们希望将学生分为年龄大于2和年龄小于2两部分
Map> stuPartMap =
stuList.stream()
.collect(Collectors.partitioningBy(stu -> stu.getAge() > 2));
System.out.println(JSON.toJSONString(stuPartMap));
// 我们希望将学生按照年龄分类,年龄相同的在一组
Map> stuGroupMap =
stuList.stream()
.collect(Collectors.groupingBy(stu -> stu.getAge()));
System.out.println(JSON.toJSONString(stuGroupMap));
第一部分输出结果:
{false:[{"age":1,"name":"B"},{"age":2,"name":"C"}],true:[{"age":3,"name":"A"},{"age":3,"name":"E"},{"age":4,"name":"D"}]}
第二部分输出结果:
{1:[{"age":1,"name":"B"}],2:[{"age":2,"name":"C"}],3:[{"age":3,"name":"A"}, {"age":3,"name":"E"}],4:[{"age":4,"name":"D"}]}
显然,我们完全可以使用groupingBy函数代替partitioningBy函数,比如第一部分我们也可以写成下面的形式:
Map> stuGroupMap1 =
stuList.stream().collect(Collectors.groupingBy(stu -> stu.getAge() > 2));
方法引用是java8针对lambda表达式所提供的的一种简化语法,其本质是lambda表达式。前面提到的例子中,比如我们希望从stuList中获取stu的name集合,我们的一般的写法是:
List nameList =
stuList.stream().map(stu -> stu.getName()).collect(Collectors.toList());
但是有了方法引用之后,我们可以更简化的写成下面的形式:
List nameList =
stuList.stream().map(Student::getName).collect(Collectors.toList());
这里面Student::getName其实就是对lambda表示 stu->stu.getName() 的简化。更为常见的用法是System.out.println方法。
stuList.forEach(stu->System.out.println(stu));
stuList.forEach(System.out::println);
还有转Map的时候:
Map stuFilterMap =
stuList.stream()
.collect(Collectors.toMap(stu -> stu.getAge(), stu -> stu));
Map stuFilterMap =
stuList.stream()
.collect(Collectors.toMap(Student::getAge, stu -> stu));
方法引用共分为四类:
删除集合中满足条件的元素,不会出现UnmodifiedException
//删除年龄小于等于2的学生
stuList.removeIf(stu -> stu.getAge() <= 2);
对集合中的所有元素执行Function函数,并使用执行的结果替代原始元素,一般用于对字符串的操作(复杂对象可以直接使用foreach处理)
List phones = Arrays.asList("186-1001-8262", "186-1001-8263",
"186-1001-8264");
//需要将手机号码中的-去掉
phones.replaceAll(phone -> phone.replace("-", ""));
这是List接口的方法,用于对元素按照跟定的规则排序
//对学生列表按照年龄升序排列
stuList.sort((stu1, stu2) -> stu1.getAge() - stu2.getAge());
类似于集合的forEach方法,不同的是传入的是两个参数
map.forEach((k, v) -> System.out.println(k + "=" + v))
获取指定key的value,不存在的返回默认的v
只有k不存在或者k对应的value为null时,才将k,v放入map
是对remove(k)方法的增强,只有当k对应的value和v相等时才删除
对Map中的每个key对应的元素执行Function操作,得到的结果替换原来的value
如果map中的key对应的value不存在或者为null,就将v放入k。否则就执行BiFunction,执行的结果如果不为null就和k关联#### java8-Predicate
Predicate是个函数式接口,和Function接口一样,不同的是Predicate接口的定义为Predicate
根据函数式接口的规定,只能有一个抽象方法,Predicate接口总共有三个主要的方法,一个抽象方法test和两个default方法and和or。
boolean test(T t);
用于检测实现类中的语句是true或false
default Predicate
连接两个Predicate
default Predicate
连接两个Predicate
比如下面的代码用于检测Student对象的年龄是否大于2
public static void main(String[] args) {
Student stu = new Student("A", 3);
System.out.println(testPredicate(stu, s -> s.getAge() > 2));
}
public static boolean testPredicate(T t, Predicate predicate) {
return predicate.test(t);
}
Predicate接口一般和Stream的filter方法结合使用,用来过滤集合中的元素。
Stream是java8基于函数式编程而出现的用于集合复杂操作的工具类,Stream的中文翻译是流、流式。字面感觉和java的IO很像,但其实没有任何的关联。Stream是以一种流式处理的思想对集合的元素进行处理。
Stream的出现基于著名的大数据并行处理思想MapReduce,MapReduce思想最早由谷歌公司提出,用来解决其搜索性能问题,后来发展成为一种通用的大数据并行处理思想。MapReduce是基于函数式编程中的Map函数和Reduce函数得来,Map函数对待处理的数据进行遍历处理,Reduce函数对Map之后的数据进行迭代式处理。
举个例子:如果有一堆数据,里面包含整型、浮点型甚至字符串,现在要求对其中的整型进行求和,显然必须先对数据遍历处理,过滤或者转换的方式得到整型,然后对得到的整型数据进行迭代式的求和。这其中的前半部分就是Map函数所做的事,后半部分就是Reduce函数做的事。
简而言之一句话:Map是对数据遍历得到想要的数据,Reduce对想要的数据进行处理得到最终想要的结果。
要了解Stream,先看下面一部分代码:
public static void main(String[] args) {
List stuList = new ArrayList<>();
stuList.add(new Student("A", 1));
stuList.add(new Student("B", 3));
stuList.add(new Student("C", 2));
stuList.add(new Student("D", 4));
List stuNameList = stuList
.stream()
.filter(stu ->stu.getAge() > 1)
.sorted((stu1, stu2) -> stu1.getAge() - stu2.getAge())
.map(stu->stu.getName())
.collect(Collectors.toList());
System.out.println(JSON.toJSONString(stuNameList));
}
上面这段代码的最终输出结果是
["C","B","D"]
整段代码的含义是从给定的学生列表stuList中,筛选出age大于1的学生,并且按照学生的age升序排列,最后得到学生name的集合。
在java8出现Stream之前,我们要实现上面的功能,一行代码肯定解决不了。这就是Stream的强大之处。
上面的代码主要涉及下面几个方法:
从对上面几个方法的简单讲解,结合Steam的MapReduce思想,Stream的方法或者Stream的处理流程总共分为3部分。
值得注意的是Stream在调用终止方法之前,不会立即执行stream中的处理方法,也就是所有对Stream的处理操作都会延迟到最终的终止方法调用时再执行。这一点和Spark很像,spark框架是一种并行的大数据处理框架,其核心思想是RDD(弹性分布式数据集),每个rdd支持两种操作Transformation和action,所有的变换在最终的action之前都不会立即执行,而是在action之时再执行。因此只要没有调用最终的终止方法,Stream所属对象的集合可以进行增删改的操作
Stream常用的获取方式有两种,Stream静态方法(java8接口支持静态方法)和Collection中的stream()方法。Stream的静态方法包含两个:
of(T t)
返回一个只有一个元素的Stream
of(T... values)
返回一个包含values的Stream
如下我代码我们希望从给定的字符串数组中过滤出包含字母b的元素,并将b替换为B
String[] sarray = { "abc", "bcd", "cde" };
List sList = Stream.of(sarray)
.filter(s ->s.contains("b"))
.map(s -> s.replace("b", "B"))
.collect(Collectors.toList());
System.out.println(JSON.toJSONString(sList));
静态方法一般用来处理非集合的数据源很方便,避免将数组先转换为集合的困扰。
Collection接口定义了stream()方法,用来获取集合的流对象,根据对java8接口增强的了解,这个方法肯定是default方法。
Stream中元素的处理就是MapReduce思想中的Map过程(此Map并不等同于stream中的map方法),处理之后会得到一个新的Stream。Stream中对元素的处理方法很多,除了前面提到的最常用的filter、map、sorted之外,还有如下几个重要方法:
distinct() 无参数,过滤Stream中的重复元素,得到是无重复元素的Stream,重复元素的依据是元素的equals方法
peek(Consumer) peek接收的参数为Consumer类型,Consumer在之前讲到过接收一个T类型参数,无返回值,这是peek方法和map方法的主要区别,peek用来处理无返回值的操作,比如打印元素,而map用来处理有返回值的操作。
sorted() 和上面的带参数的sorted一样,只不过这个无参数,按照对象自定义的Comparator接口实现。如果对象未实现Comparator接口会报错。
skip(long) 跳过Stream中的前n个元素,如果Stream元素个数小于n,返回空的stream
limit(long) 获取Stream中的前n个元素,如果Stream元素个数小于n,返回全部元素
Stream的终结就是MapReduce思想中的Reduce过程(此Reduce也不等同于Stream中的reduce方法),Stream的常用终结方法除上面提到的collect方法之外,还包括以下几种:
Optional提供了一种安全的获取值的方式,避免之前为了防止出现NPE而进行繁琐的检查的工作。Optional有很多方法,常用的方法或者组合使用方式为:
组合方式:一般对一个方法的返回值使用Optional包装,然后使用ifPresent执行不为空的操作,或者使用orElseGet方法获取方法的返回值或者默认值。
System.out.println(Optional.ofNullable(null).orElseGet(() -> {
return "NULL";
}));//输出NULL
System.out.println(Optional.ofNullable("ss").orElseGet(() -> {
return "NULL";
}));//输出ss
Optional.ofNullable(null).ifPresent(System.out::println);//无输出
Optional.ofNullable("sss").ifPresent(System.out::println);//输出sss
Stream的collect方法接收一个Collector对象,Collector的官方解释是对Stream的可变减少操作。不太理解这里的可变减少是什么含义。
Collector主要有两方面的能力:
这是Collector最常见的用法,常见的操作是将Stream中的元素转为List,Set或者Map,而这三者在Collector对应的工具类Collectors中都有具体的方法可用:
Collectors.toList(),Collectors.toSet(),Collectors.toMap(Function key,Function value)
除了转List和Set不需要参数之外,转Map的方法接收两个Function函数,用来决定key和value如何生成。
下面的代码演示了如何将stuList中满足年龄大于1的学生收集到List,Set以及按照name对应stu转成Map
List stuList = new ArrayList<>();
stuList.add(new Student("B", 1));
stuList.add(new Student("A", 3));
stuList.add(new Student("A", 3));
stuList.add(new Student("C", 2));
stuList.add(new Student("D", 4));
List stuFilterList =
stuList.stream()
.filter(stu ->stu.getAge() > 1)
.collect(Collectors.toList());
System.out.println(JSON.toJSONString(stuFilterList));
Set stuFilterSet =
stuList.stream()
.filter(stu ->stu.getAge() > 1)
.collect(Collectors.toSet());
System.out.println(JSON.toJSONString(stuFilterSet));
Map stuFilterMap =
stuList.stream()
.filter(stu -> stu.getAge() > 1)
.collect(Collectors.toMap(stu -> stu.getAge(), stu -> stu));
System.out.println(JSON.toJSONString(stuFilterMap));
上面的代码运行结果为:
[{"age":3,"name":"A"},{"age":3,"name":"A"},{"age":2,"name":"C"},{"age":4,"name":"D"}]
[{"age":4,"name":"D"},{"age":2,"name":"C"},{"age":3,"name":"A"}]
Exception in thread "main" java.lang.IllegalStateException: Duplicate key
com.zong.test.Student@45f......
转List和Set都得到了我们预期的结果,Set中也对元素做了去重(Student类重写了hashcode和equals方法),但是转Map却抛出了Key重复的异常,原因是因为我们使用age作为可以,而其中有两个元素的age都为3,因此出现异常。在绝大数的使用场景下,这种情况很普遍,因此Collectors还额外提供了支持处理重复key的toMap方法
toMap(Function key,Function value,BinaryOperator mergeFunction)
三个参数中,前两个参数和之前的toMap方法含义一样,定义了获取key和value的方式,第三个参数定义了当有重复key的时候应当做的操作。上面的代码我们修改成如下即可:
Map stuFilterMap =
stuList.stream()
.filter(stu -> stu.getAge() > 1)
.collect(Collectors.toMap(stu -> stu.getAge(), stu -> stu, (stu1, stu2) -> stu2));
System.out.println(JSON.toJSONString(stuFilterMap));
其中的 (stu1, stu2) -> stu2 表示当遇到重复元素时保留新的值,我们如果希望当遇到重复的key时判断name的长度,name较长的保留,则可以写成下面的方式:
Map stuFilterMap =
stuList.stream()
.filter(stu -> stu.getAge() > 1)
.collect(Collectors.toMap(stu -> stu.getAge(), stu -> stu,
(stu1, stu2) -> stu1.getName().length() > stu2.getName().length() ? stu1 : stu2));
System.out.println(JSON.toJSONString(stuFilterMap));
Collector的另一个功能是对Stream中的元素进行分组,在Collectors中同样提供对应的方法,常用的分组方法有两个。
partitioningBy(Predicate)
接收一个Predicate对象,按照元素在Predicate中的结果分为true和false两部分
groupingBy(Function)
接收一个Function函数,分组的结果是根据Function函数的输出结果作为key,不同的元素在Function函数中的输出结果相同的在同一个key下
下面代码分别演示两个函数的使用。
List stuList = new ArrayList<>();
stuList.add(new Student("B", 1));
stuList.add(new Student("A", 3));
stuList.add(new Student("E", 3));
stuList.add(new Student("C", 2));
stuList.add(new Student("D", 4));
// 我们希望将学生分为年龄大于2和年龄小于2两部分
Map> stuPartMap =
stuList.stream()
.collect(Collectors.partitioningBy(stu -> stu.getAge() > 2));
System.out.println(JSON.toJSONString(stuPartMap));
// 我们希望将学生按照年龄分类,年龄相同的在一组
Map> stuGroupMap =
stuList.stream()
.collect(Collectors.groupingBy(stu -> stu.getAge()));
System.out.println(JSON.toJSONString(stuGroupMap));
第一部分输出结果:
{false:[{"age":1,"name":"B"},{"age":2,"name":"C"}],true:[{"age":3,"name":"A"},{"age":3,"name":"E"},{"age":4,"name":"D"}]}
第二部分输出结果:
{1:[{"age":1,"name":"B"}],2:[{"age":2,"name":"C"}],3:[{"age":3,"name":"A"}, {"age":3,"name":"E"}],4:[{"age":4,"name":"D"}]}
显然,我们完全可以使用groupingBy函数代替partitioningBy函数,比如第一部分我们也可以写成下面的形式:
Map> stuGroupMap1 =
stuList.stream().collect(Collectors.groupingBy(stu -> stu.getAge() > 2));
方法引用是java8针对lambda表达式所提供的的一种简化语法,其本质是lambda表达式。前面提到的例子中,比如我们希望从stuList中获取stu的name集合,我们的一般的写法是:
List nameList =
stuList.stream().map(stu -> stu.getName()).collect(Collectors.toList());
但是有了方法引用之后,我们可以更简化的写成下面的形式:
List nameList =
stuList.stream().map(Student::getName).collect(Collectors.toList());
这里面Student::getName其实就是对lambda表示 stu->stu.getName() 的简化。更为常见的用法是System.out.println方法。
stuList.forEach(stu->System.out.println(stu));
stuList.forEach(System.out::println);
还有转Map的时候:
Map stuFilterMap =
stuList.stream()
.collect(Collectors.toMap(stu -> stu.getAge(), stu -> stu));
Map stuFilterMap =
stuList.stream()
.collect(Collectors.toMap(Student::getAge, stu -> stu));
方法引用共分为四类:
删除集合中满足条件的元素,不会出现UnmodifiedException
//删除年龄小于等于2的学生
stuList.removeIf(stu -> stu.getAge() <= 2);
对集合中的所有元素执行Function函数,并使用执行的结果替代原始元素,一般用于对字符串的操作(复杂对象可以直接使用foreach处理)
List phones = Arrays.asList("186-1001-8262", "186-1001-8263",
"186-1001-8264");
//需要将手机号码中的-去掉
phones.replaceAll(phone -> phone.replace("-", ""));
这是List接口的方法,用于对元素按照跟定的规则排序
//对学生列表按照年龄升序排列
stuList.sort((stu1, stu2) -> stu1.getAge() - stu2.getAge());
类似于集合的forEach方法,不同的是传入的是两个参数
map.forEach((k, v) -> System.out.println(k + "=" + v))
获取指定key的value,不存在的返回默认的v
只有k不存在或者k对应的value为null时,才将k,v放入map
是对remove(k)方法的增强,只有当k对应的value和v相等时才删除
对Map中的每个key对应的元素执行Function操作,得到的结果替换原来的value
如果map中的key对应的value不存在或者为null,就将v放入k。否则就执行BiFunction,执行的结果如果不为null就和k关联