lamdba03 Java8新特性之四:Stream API
2021/4/26 14:25:22
本文主要是介绍lamdba03 Java8新特性之四:Stream API,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
Java8新特性之四:Stream API
- 例如
- Stream的操作步骤
- 举个简单的例子:
- Stream中间操作--筛选与切片 与parallelStream并行流
- limit举例
- skip举例
- distinct举例
- Stream中间操作--映射
- map举例
- 总结
- 终止操作--查找与匹配
- allMatch检查是否至少匹配一个元素
- findAny返回当前流中的任意元素
- max-返回流中最大值
- 归约
- 求一个1到100的和
- 求所有人的年龄之和
- 求所有人的平均年龄
- 求所有人的年龄的集合
- 求集合中所有人的最大年龄
- 注意流的关闭
- 完整测试代码
Java8的两个重大改变,一个是Lambda表达式,另一个就是Stream API表达式。 Stream 是Java8中处理集合的关键抽象概念,它可以对集合进行非常复杂的查找、过滤、筛选等操作,在新版的JPA【连接数据库】中,也已经加入了Stream。
Stream API给我们操作集合带来了强大的功用,同时Stream API操作简单,容易上手。
例如
@Query("select u from User u") Stream<User> findAllByCustomQueryAndStream(); Stream<User> readAllByFirstnameNotNull(); @Query("select u from User u") Stream<User> streamAllPaged(Pageable pageable);
Stream的操作步骤
Stream有如下三个操作步骤:
一、创建Stream
从一个数据源,如集合、数组中获取流。
二、中间操作
一个操作的中间链,对数据源的数据进行操作。
三、终止操作
一个终止操作,执行中间操作链,并产生结果。
注意:对流的操作完成后需要进行关
举个简单的例子:
假设有一个Person类和一个Person列表,现在有两个需求:1)找到年龄大于18岁的人并输出;2)找出所有中国人的数量。
@Data class Person { private String name; private Integer age; private String country; private char sex; public Person(String name, Integer age, String country, char sex) { this.name = name; this.age = age; this.country = country; this.sex = sex; } }
List<Person> personList = new ArrayList<>(); personList.add(new Person("欧阳雪",18,"中国",'F')); personList.add(new Person("Tom",24,"美国",'M')); personList.add(new Person("Harley",22,"英国",'F')); personList.add(new Person("向天笑",20,"中国",'M')); personList.add(new Person("李康",22,"中国",'M')); personList.add(new Person("小梅",20,"中国",'F')); personList.add(new Person("何雪",21,"中国",'F')); personList.add(new Person("李康",22,"中国",'M'));
在JDK8以前,我们可以通过遍历列表来完成。但是在有了Stream API后,可以这样来实现:
public static void main(String[] args) { List<Person> personList = new ArrayList<>(); personList.add(new Person("欧阳雪", 18, "中国", 'F')); personList.add(new Person("Tom", 24, "美国", 'M')); personList.add(new Person("Harley", 22, "英国", 'F')); personList.add(new Person("向天笑", 20, "中国", 'M')); personList.add(new Person("李康", 22, "中国", 'M')); personList.add(new Person("小梅", 20, "中国", 'F')); personList.add(new Person("何雪", 21, "中国", 'F')); personList.add(new Person("李康", 22, "中国", 'M')); // 1)找到年龄大于18岁的人并输出; //创建stream对象 boolean test(T t); void accept(T t); personList.stream().filter(t->t.getAge()>20).forEach(t->System.out.println(t)); // lamdba 里面的方法引用 personList.stream().filter(t->t.getAge()>20).forEach(System.out::println); // 2)找出所有中国人的数量。 count()计算数量 long c = personList.stream().filter(t -> t.getCountry().equals("中国")).count(); System.out.println(c); }
在这个例子中,personList.stream()是创建流,filter()属于中间操作,forEach、count()是终止操作。
Stream中间操作–筛选与切片 与parallelStream并行流
filter:接收Landba,从流中排除某些操作
limit:截断流,使其元素不超过给定对象
skip(n):跳过元素,返回一个扔掉了前n个元素的流,若流中不足n个,则返回一个空流,与limit(n)互补
distinct:筛选,通过流所生成元素的hashCode()和equals()去除重复元素。
limit举例
需求,从Person列表中取出两个女性。
// 从Person列表中取出两个女性。 limit personList.stream().filter(t -> t.getSex() == 'F').limit(2).forEach(System.out::println);
skip举例
从Person列表中从第2个女性开始,取出所有的女性。
// 从Person列表中从第2个女性开始,取出所有的女性。 skip(1)表示跳过第一个 personList.stream().filter(t->t.getSex()=='F').skip(1).forEach(System.out::println);
distinct举例
// 去重 personList.stream().distinct().forEach(System.out::println);
Stream中间操作–映射
- map–接收Lambda,将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
- flatMap–接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
map举例
比如,我们用一个PersonCountry类来接收所有的国家信息
// 比如,我们用一个PersonCountry类来接收所有的国家信息 R apply(T t); personList.stream().map(t->t.getCountry()).forEach(System.out::println);
接收所有的姓名和国家 首先封装一个两个字段的实体类
// 接收所有的姓名和国家 首先封装一个两个字段的实体类 personList.stream().map(t->new NameAndCountry(t.getName(),t.getCountry())).forEach(System.out::println);
@Data @AllArgsConstructor @NoArgsConstructor class NameAndCountry{ private String name; private String country; }
对前面的personList按照年龄从小到大排序,年龄相同,再按照姓名排序
//对前面的personList按照年龄从小到大排序,年龄相同,再按照姓名排序 //使用无参必须该类实现自然排序 // personList.stream().sorted(); // int compare(T o1, T o2); // 第一种方法 personList.stream().sorted((o1, o2) -> { if (o1.getAge() == o2.getAge()) { return o1.getName().compareTo(o2.getName()); } return o1.getAge() - o2.getAge(); }).forEach(System.out::println); System.out.println("-----------------"); //第二种方法 使用三目运算符 personList.stream().sorted((o1, o2) ->o1.getAge()==o2.getAge()?o1.getName().compareTo(o2.getName()):o1.getAge()-o2.getAge()).forEach(System.out::println);
总结
1. filter(Predicate) 2. limit(long) 3. skip(long) 4. distinct(); 5. map(Function) 6. sorted() | sorted(Comparator)
终止操作–查找与匹配
- allMatch–检查是否匹配所有元素
- anyMatch–检查是否至少匹配一个元素
- noneMatch–检查是否没有匹配所有元素
- findFirst–返回第一个元素
- findAny–返回当前流中的任意元素
- count–返回流中元素的总个数
- max–返回流中最大值
- min–返回流中最小值
这些方面在Stream类中都有说明,这里不一一举例,只对allMatch、max各举一例进行说明。
allMatch检查是否至少匹配一个元素
判断personList中的人是否都是大于18岁的
//检查是否至少匹配一个元素 boolean b = personList.stream().anyMatch(item -> item.getAge() >18); System.out.println(b);
判断personList中的人是否都是成年人
// 判断personList中的人是否都是中国人: boolean b1 = personList.stream().allMatch(p -> p.getCountry().equals("中国")); System.out.println(b1);
findAny返回当前流中的任意元素
//返回当前流中的任意元素 Optional<Person> any = personList.stream().findAny(); System.out.println(any); //返回当前流中的任意元素 // Person person = personList.stream().findAny().get(); Person person = personList.parallelStream().findAny().get(); System.out.println(person);
max-返回流中最大值
personList中找到年龄最大的
// 找到年龄最大的 int compare(T o1, T o2); Optional<Person> max = personList.stream().max((o1, o2) -> o1.getAge() - o2.getAge()); System.out.println(max);
归约
Stream API的归约操作可以将流中元素反复结合起来,得到一个值,有
Optional<T> reduce(BinaryOperator<T> accumulator); T reduce(T identity, BinaryOperator<T> accumulator); <U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner);
求一个1到100的和
第一种方法:
用到了reduce第二个方法:T reduce(T identity, BinaryOperator accumulator)
// 求1-100的和 规约 List<Integer> list = new ArrayList<>(); for (int i = 0; i < 10; i++) { list.add(new Random().nextInt(10)); } System.out.println(list); // R apply(T t, T u,T r); Optional<Integer> reduce = list.stream().reduce((t, u) -> t + u); System.out.println(reduce);
把这个动作拆解一下,其运算步骤模拟如下:
0 (1,2) -> 1 + 2 + 0
3 (3,4) -> 3 + 4 + 3
10 (5,6) -> 5 + 6 + 10
其运算步骤是,每次将列表的两个元素相加,并将结果与前一次的两个元素的相加结果进行累加,因此,在开始时,将identity设为0,因为第1个元素和第2个元素在相加的时候,前面还没有元素操作过
第二种方法:
Integer[] list = {1, 2, 3, 4, 5}; System.out.println(Arrays.asList(list)); Arrays.stream(list).reduce((t,u)->{ System.out.println(t+"-----"+u); return t+u; }); System.out.println(Arrays.asList(list));
求所有人的年龄之和
// 求所有人的年龄之和 Optional<Integer> reduce = personList.stream().map(item -> item.getAge()).reduce((t, u) -> t + u); System.out.println(reduce);
求所有人的平均年龄
Collectors.averagingDouble
//averagingDouble Double collect1 = personList.stream().collect(Collectors.averagingDouble(t -> t.getAge())); System.out.println(collect1);
求所有人的年龄的集合
collect(Collectors.toList())
List<Integer> collect = personList.stream().map(item -> item.getAge()).collect(Collectors.toList());
求集合中所有人的最大年龄
// 求出集合中最大年龄 Optional<Person> collect2 = personList.stream().collect(Collectors.maxBy((o1, o2) -> o1.getAge() - o2.getAge())); System.out.println(collect2);
最小年龄类型。
还有其他很操作,可以参考java.util.stream.Collectors。
注意流的关闭
求集合中所有人的最小年龄。
try(final Stream<Integer> integerStream = personList.stream().map(Person::getAge)) { final Optional<Integer> minAge = integerStream.collect(Collectors.minBy(Integer::compareTo)); System.out.println(minAge.get()); }
最好将流的操作放到try-with-resources,本章前面内容为了方便,没有放到try-with-resources中。
完整测试代码
package com.zz.lamdab.lamdba04; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.stream.Stream; public class Deom1 { public static void main(String[] args) { List<Person> personList = new ArrayList<>(); personList.add(new Person("欧阳雪", 18, "中国", 'F')); personList.add(new Person("Tom", 24, "美国", 'M')); personList.add(new Person("Harley", 22, "英国", 'F')); personList.add(new Person("向天笑", 20, "中国", 'M')); personList.add(new Person("李康", 22, "中国", 'M')); personList.add(new Person("小梅", 20, "中国", 'F')); personList.add(new Person("何雪", 21, "中国", 'F')); personList.add(new Person("李康", 22, "中国", 'M')); // 1)找到年龄大于18岁的人并输出; //创建stream对象 boolean test(T t); void accept(T t); personList.stream().filter(t -> t.getAge() > 20).forEach(t -> System.out.println(t)); // lamdba 里面的方法引用 personList.stream().filter(t -> t.getAge() > 20).forEach(System.out::println); // 2)找出所有中国人的数量。 count()计算数量 long c = personList.stream().filter(t -> t.getCountry().equals("中国")).count(); System.out.println(c); // 从Person列表中取出两个女性。 limit personList.stream().filter(t -> t.getSex() == 'F').limit(2).forEach(System.out::println); // 从Person列表中从第2个女性开始,取出所有的女性。 skip(1)表示跳过第一个 personList.stream().filter(t -> t.getSex() == 'F').skip(1).forEach(System.out::println); System.out.println("-----------------"); // 去重 personList.stream().distinct().forEach(System.out::println); System.out.println("-----------------"); // 比如,我们用一个PersonCountry类来接收所有的国家信息 R apply(T t); personList.stream().map(t -> t.getCountry()).forEach(System.out::println); // 接收所有的姓名和国家 首先封装一个两个字段的实体类 personList.stream().map(t -> new NameAndCountry(t.getName(), t.getCountry())).forEach(System.out::println); System.out.println("-----------------"); //对前面的personList按照年龄从小到大排序,年龄相同,再按照姓名排序 //使用无参必须该类实现自然排序 // personList.stream().sorted(); // int compare(T o1, T o2); // 第一种方法 personList.stream().sorted((o1, o2) -> { if (o1.getAge() == o2.getAge()) { return o1.getName().compareTo(o2.getName()); } return o1.getAge() - o2.getAge(); }).forEach(System.out::println); System.out.println("-----------------"); //第二种方法 使用三目运算符 personList.stream().sorted((o1, o2) ->o1.getAge()==o2.getAge()?o1.getName().compareTo(o2.getName()):o1.getAge()-o2.getAge()).forEach(System.out::println); System.out.println("-----------------"); //返回当前流中的任意元素 Optional<Person> any = personList.stream().findAny(); System.out.println(any); System.out.println("-----------------"); // 检查是否至少匹配一个元素 boolean b = personList.stream().anyMatch(item -> item.getAge() >18); System.out.println(b); // 判断personList中的人是否都是中国人: boolean b1 = personList.stream().allMatch(p -> p.getCountry().equals("中国")); System.out.println(b1); //返回当前流中的任意元素 // Person person = personList.stream().findAny().get(); Person person = personList.parallelStream().findAny().get(); System.out.println(person); // 找到年龄最大的 int compare(T o1, T o2); Optional<Person> max = personList.stream().max((o1, o2) -> o1.getAge() - o2.getAge()); System.out.println(max); // 求所有人的年龄之和 Optional<Integer> reduce = personList.stream().map(item -> item.getAge()).reduce((t, u) -> t + u); System.out.println(reduce); List<Integer> collect = personList.stream().map(item -> item.getAge()).collect(Collectors.toList()); //averagingDouble Double collect1 = personList.stream().collect(Collectors.averagingDouble(t -> t.getAge())); System.out.println(collect); System.out.println(collect1); // 求出集合中最大年龄 Optional<Person> collect2 = personList.stream().collect(Collectors.maxBy((o1, o2) -> o1.getAge() - o2.getAge())); System.out.println(collect2); // 注意流的关闭 // Stream<Integer> integerStream = personList.stream().map(Person::getAge); try(final Stream<Integer> integerStream = personList.stream().map(Person::getAge)) { final Optional<Integer> minAge = integerStream.collect(Collectors.minBy(Integer::compareTo)); System.out.println(minAge.get()); } } } @Data class Person { private String name; private Integer age; private String country; private char sex; public Person(String name, Integer age, String country, char sex) { this.name = name; this.age = age; this.country = country; this.sex = sex; } } @Data @AllArgsConstructor @NoArgsConstructor class NameAndCountry { private String name; private String country; }
这篇关于lamdba03 Java8新特性之四:Stream API的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-26Java语音识别项目资料:新手入门教程
- 2024-11-26JAVA语音识别项目资料:新手入门教程
- 2024-11-26Java语音识别项目资料:入门与实践指南
- 2024-11-26Java云原生资料入门教程
- 2024-11-26Java云原生资料入门教程
- 2024-11-26Java云原生资料:新手入门教程
- 2024-11-25Java创意资料:新手入门的创意学习指南
- 2024-11-25JAVA对接阿里云智能语音服务资料详解:新手入门指南
- 2024-11-25Java对接阿里云智能语音服务资料详解
- 2024-11-25Java对接阿里云智能语音服务资料详解