Fork me on GitHub

小L 的个人博客

生活虽不能自由,但愿心能自由。

  menu
10 文章
0 评论
22108 浏览
0 当前访客
ღゝ◡╹)ノ❤️
生活虽不能自由,但愿心能自由

Java8的Stream操作详解

Java8新增集合的Stream流操作

阅览本文章时,请确保您了解Java8的Lambda表达式。
Java8 Stream流不同于Java以往中的InputStream和OutputStream流,Java8中的Stream对Collection集合的集合操作有了极大的增强。Stream流使用Java8新特性Lambda表达式对集合进行操作,方便了代码的可读性及便利性。同时,Stream流支持并行操作,增加了对多核处理器的支持。
Stream流操作分为多个中间操作(如:Stream.filter()是一个中间操作)以及最终操作(如:Stream.foreach()是一个最终操作), 源数据上的计算仅在终端操作启动时执行, 源元素仅在需要时才被使用。

以下案例为流操作中的中间操作

案例 1.集合元素过滤

以下代码过滤掉集合中字符串长度小于2的元素

List<String> list = new ArrayList<>();
list.add("1");
list.add("11");
list.add("111");
list.add("1111");
Stream<String> filterStream =  list.stream().filter((str) -> str.length() >= 2);

案例 2.集合元素大小限定
以下代码保留集合前2个的元素

List<String> list = new ArrayList<>();
list.add("1");
list.add("11");
list.add("111");
list.add("1111");
Stream<String> limitStream = list.stream().limit(2);

案例 3.集合元素去重
去重时,根据元素的equals()方法检测重复的元素

List<String> list = new ArrayList<>();
list.add("1");
list.add("11");
list.add("111");
list.add("1111");
Stream<String> distinctStream = list.stream().distinct();

案例 4. 对集合每个元素操作生成一个新的Stream流之后,将每一个Stream流合并生成最终流
以下代码展示了获取所有订单Order中所有订单明细OrderItem

List<Order> orders = new ArrayList<>();
orders.add(new Order());
orders.add(new Order());
Stream<Order.OrderItem> flatMapStream = orders.stream().flatMap((order) -> order.orderItems.stream());

案例 5. 将该集合的Stream流映射成另一类型的Stream流
以下代码展示了将Order类型的Stream流映射成Long类型的Stream流

List<Order> list = new LinkedList<>();
list.add(new Order());
list.add(new Order());
Stream<Long> longStream = list.stream().map((order) -> order.getId());

案例 6.对集合流进行的一系列中间操作后,每个中间操作后对返回的结果集流打印结果集的元素
以下代码展示了过滤字符串长度小于2后,然后打印过滤后的List.通常用于debug调试,在进行每一次中间操作后查看本次操作的结果

List<String> list = new ArrayList<>();
list.add("1");
list.add("11");
list.add("111");
list.add("1111");
Stream<String> peek = list.stream().filter((str) -> str.length() >= 2).peek((str) -> System.out.println("filter String:" + str));

案例 6. 集合流跳过前n个元素
需要注意的是,如果是有序并行流,则此操作的代价很昂贵。如果需要使用并行流,则应该删除使用unordered()排序约束,或者使用sequential()切换为顺序流。

List<Order> list = new LinkedList<>();
Order order1 = new Order();
order1.setId(1L);
list.add(order1);
list.add(new Order());
Stream<Order> skipStream = list.stream().skip(2);

案例 7. 流排序
根据流元素的长度升序

List<String> list = new ArrayList<>();
list.add("11");
list.add("111111");
list.add("111");
list.add("1111");
Stream<String> sortedStream = list.stream().sorted(Comparator.comparingInt(String::length));

以下案例为流操作中的终端操作

案例 1. 集合流中所有元素都满足断言Predicate

以下代码展示了集合中所有元素长度必须大于1时,返回true。当流为空时,直接返回true。

List<String> list = new ArrayList<>();
list.add("111");
list.add("222");
list.add("33");
boolean allMatch = list.stream().allMatch((str) -> str.length() > 1);

案例 2. 集合流中任意元素满足断言Predicate
以下代码展示了集合中任一元素长度大于2时,返回true。当流为空时,直接返回false。

List<String> list = new ArrayList<>();
list.add("11");
list.add("222");
list.add("33");
boolean anyMatch = list.stream().anyMatch((str) -> str.length() > 2);

案例 3.计算流任意元素都不满足断言Predicate
当所有流元素都不满足Predicate时,返回true。如果流为空,返回true。

List<String> list = new ArrayList<>();
list.add("11");
list.add("222");
list.add("33");
boolean noneMatch = list.stream().noneMatch((str) -> str.length() > 3);

案例 4.计算集合流中元素个数

List<String> list = new ArrayList<>();
list.add("11");
list.add("222");
list.add("33");
long count = list.stream().count();

案例 5.返回集合流中任一元素
如果流未排序,则可能返回任一元素

List<String> list = new ArrayList<>();
list.add("11");
list.add("222");
list.add("33");
Optional<String> any = list.parallelStream().findAny();

案例 6.返回流中元素最大者(根据Comparator比较)

List<String> list = new ArrayList<>();
list.add("11");
list.add("222");
list.add("33");
Optional<String> max = list.stream().max(Comparator.comparingInt(String::length));

案例 7.返回流中元素最小者(根据Comparator比较)

List<String> list = new ArrayList<>();
list.add("11");
list.add("222");
list.add("33");
Optional<String> min = list.stream().min(Comparator.comparingInt(String::length));

示例代码8:缩减操作

使用一个提供的初始值(identity)、累积函数(accumulation)和结合函数(combining),
其中accumulation要满足associativenon-interferingstatelesscombining要满足associativenon-interferingstateless。用伪代码表示则为:

U result = identity;
for (T element : this stream)
result = accumulator.apply(result, element)
return result;

要注意,这不一定按顺序执行。

对于顺序流accumulator函数用于计算,combiner函数不参与计算。
accumulator function 第一个参数为初始值或为accumulator function 返回值, 第二个参数为流元素值

List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(4);
String reduce = list.stream().reduce("aa", (str, t1) -> str + t1, (str1, str2) ->str2);

打印出reduce值:aa124

对于并行流,将流分区,每个分区使用accumulator函数计算最终结果,每个分区的结果和初始值(只参与一次计算)用于combiner函数。

Set<Integer> list = new HashSet<>();
list.add(1);
list.add(2);
list.add(4);
list.add(8);
list.add(9);
list.add(10);
Integer reduce = list.parallelStream().reduce(1, Integer::sum, Integer::sum);

打印出reduce值:38

示例9: 收集器
1.求平均值

List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(4);
list.add(8);
Double avg= list.stream().collect(Collectors.averagingInt(Integer::intValue));

2.适配一个收集器并转换结果类型

List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(4);
list.add(8);
List<Integer> integerList = list.stream().collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));

3.求元素数

List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(4);
list.add(8);
Long count = list.stream().collect(Collectors.counting());

4.分组

List<Person> list = new ArrayList<>();
Person person = new Person();
person.setCity("SH");
Person person1 = new Person();
person1.setCity("WH");
Person person2 = new Person();
person2.setCity("WH");
list.add(person);
list.add(person1);
list.add(person2);
HashMap<String, List<Person>> listHashMap = list.stream().collect(Collectors.groupingBy(Person::getCity, HashMap::new, Collectors.toList()));

根据城市分组,计算出每个城市的Person的集合。如果需要返回可并发Map集合,请使用Collectors.groupingByConcurrent

5.join操作
使用分隔符","来连接集合元素

List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
String collect = list.stream().collect(Collectors.joining(",", "", ""));

6.mapping
获得所有Person分布的城市

List<Person> list = new ArrayList<>();
Person person = new Person();
person.setCity("SH");
Person person1 = new Person();
person1.setCity("WH");
Person person2 = new Person();
person2.setCity("WH");
list.add(person);
list.add(person1);
list.add(person2);
Set<String> collect = list.stream().collect(Collectors.mapping(Person::getCity, Collectors.toSet()));

7.最大值

List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(4);
list.add(8);
Optional<Integer> collect = list.stream().collect(Collectors.maxBy(Comparator.comparingInt(Integer::intValue)));

8.最小值

List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(4);
list.add(8);
Optional<Integer> collect = list.stream().collect(Collectors.minBy(Comparator.comparingInt(Integer::intValue)));

9.分区分组
集合元素根据能否被2整除分组。

List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(4);
list.add(8);
Map<Boolean, List<Integer>> booleanListMap = list.stream().collect(Collectors.partitioningBy((t) ->t.intValue()%2==0, Collectors.toList()));

10.缩减(reduce)操作,同上
11.统计
获取总数、和、最小值、最大值、平均值。

List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(4);
list.add(8);
IntSummaryStatistics collect = list.stream().collect(Collectors.summarizingInt(Integer::intValue));

12.求和

List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(4);
list.add(8);
Integer collect1 = list.stream().collect(Collectors.summingInt(Integer::intValue));

生活虽不能自由,但愿心能自由。
评论