> 技术文档 > Java中的Stream流(保姆级别!!)_java stream

Java中的Stream流(保姆级别!!)_java stream


如果您觉得有帮助的话,可以收藏防止找不到~ 

1、Stream流概述

java 8是一个非常成功的版本,这个版本新增的Stream 、配合同版本出现的 Lambda、大大简化了操作集合和数组。

究竟什么是Stream?

首先,为了方便大家理解,我们类比于生产瓶子的流水线

1.1 生产瓶子的工厂流水线

把所有瓶子放在流水线上,准备处理

检查瓶子,消毒,灌装,密封就相当于是中间操作,淘汰不符合的瓶子,添加想要的操作

以上就是工产流水线上的完整操作,那么什么是

1.2 Stream流的思想

比如说我们现在要处理集合,我们首先把集合中的所有元素放到生产线上,按照我们想要的操作一步一步处理

这就是流,简单理解,就是流水线操作,而且这些步骤不会立刻执行,等你喊一声 “开始”,所有数据就会顺着流水线走一遍,自动完成所有加工,最后直接得到你想要的结果,非常方便高效~

1.3 Stream流的总述

这是张概述图,大家大致了解本文的核心内容,不懂的地方后面我会给大家讲明白的~

2、Stream与传统遍历对比

几乎所有的集合(如 Collection 接口或 Map 接口等)都支持直接或间接的遍历操作。而当我们需要对集合中的元素进行操作的时候,除了必需的添加、删除、获取外,最典型的就是集合遍历。

需求:找到以\"张\"开头的,并且长度是3的元素打印出来

  1. 传统写法:

import java.util.ArrayList;import java.util.List; public class Demo1List { public static void main(String[] args) { List list = new ArrayList(); list.add(\"张无忌\"); list.add(\"周芷若\"); list.add(\"赵敏\"); list.add(\"小昭\"); list.add(\"李章\"); list.add(\"张三\"); list.add(\"张三丰\"); List listA = new ArrayList(); for ( String s : list) { if (s.startsWith(\"张\")) { listA.add(s); } } List listB = new ArrayList(); for (String s: listA) { if (s.length() == 3) { listB.add(s); } } for (String s: listB) { System.out.println(s); } }}

2.Stream流的写法

List list = new ArrayList(); list.add(\"张无忌\"); list.add(\"周芷若\"); list.add(\"赵敏\"); list.add(\"小昭\"); list.add(\"李章\"); list.add(\"张三\"); list.add(\"张三丰\"); // 一行就可以解决~ list.stream().filter(name -> name.startsWith(\"张\"))  .filter(name -> name.length() == 3)  .forEach(name -> System.out.println(name));

代码更加简洁高效、简单说:能用 Stream 就用 Stream,除非你需要手动控制循环细节—— 这也是 Java 8 后推荐的编码风格~

3、Stream流的创建

Stream可以通过集合数组创建

3.1 单列集合(list,set)类型、使用Collection的默认方法 java.util.Collection.stream()
 List list = Arrays.asList(\"a\", \"b\", \"c\"); // 创建一个顺序流 Stream stream = list.stream(); System.out.println(\"创建一个顺序的流~\"); stream.forEach(System.out::println); //创建一个并行流 Stream parallelStream = list.parallelStream(); System.out.println(\"创建一个并行的流~\"); parallelStream.forEach(System.out::println);

3.2 双列集合,必须先转换,才能使用Stream流(keySet()和entrySet())
 //1.创建双列集合 HashMap hm = new HashMap(); //2.添加数据 hm.put(\"张三\", 18); hm.put(\"王五\", 19); hm.put(\"赵六\", 20); hm.put(\"田七\", 21); //3.方式一:使用keySet()获取所有的键,从而获取Stream流 hm.keySet().stream().forEach(key -> System.out.println(key)); System.out.println(\"======分割=====\"); //4.方式二:使用entrySet()获取所有的键值对,从而获取Stream流 hm.entrySet().stream() .forEach(entry -> System.out.println(entry.getKey() + \":\" + entry.getValue()));

3.3 数组 使用Stream接口中的静态方法
 int[] array={1,3,5,6,8}; Arrays.stream(array).forEach(System.out::println);

Stream的顺序流和并行流的区别

如果流中的数据量足够大,并行流可以加快处速度~

除了直接创建并行流,还可以通过parallel()把顺序流转换成并行流

4.Stream的使用

在使用stream之前,先理解一个概念:Optional类

Optional 是 Java 8 引入的一个容器类,主要用于解决 空指针异常(NullPointerException) 问题。它可以包含一个非空值,或者表示空(不存在值),通过明确的 API 设计让开发者在编译期就处理可能的空值情况,而不是在运行时抛出异常。

4.1 中间方法

4.1.1 筛选(filter)

筛选,是按照一定的规则校验流中的元素,将符合条件的元素提取到新的流中的操作。

需求一:筛选出Integer集合中大于7的元素,并打印出来**

 List list = Arrays.asList(6, 7, 3, 8, 1, 2, 9); list.stream().filter(x -> x > 7).forEach(System.out::println);

需求二 筛选员工中工资高于8000的人,并形成新的集合。 形成新集合依赖collect(收集),后文有详细介绍。

public class StreamTest {public static void main(String[] args) {List personList = new ArrayList();personList.add(new Person(\"Tom\", 8900, 23, \"male\", \"New York\"));personList.add(new Person(\"Jack\", 7000, 25, \"male\", \"Washington\"));personList.add(new Person(\"Lily\", 7800, 21, \"female\", \"Washington\"));personList.add(new Person(\"Anni\", 8200, 24, \"female\", \"New York\"));personList.add(new Person(\"Owen\", 9500, 25, \"male\", \"New York\"));personList.add(new Person(\"Alisa\", 7900, 26, \"female\", \"New York\"));List fiterList = personList.stream().filter(x -> x.getSalary() > 8000).map(Person::getName).collect(Collectors.toList());System.out.print(\"高于8000的员工姓名:\" + fiterList);}}

4.1.2 映射(map)

映射,可以将一个流的元素按照一定的映射规则映射到另一个流中、主要是转换流中的数据类型。

案例一:将员工的薪资全部增加2000

 List personList = new ArrayList(); personList.add(new Person(\"Tom\", 8900, 23, \"male\", \"New York\")); personList.add(new Person(\"Jack\", 7000, 25, \"male\", \"Washington\")); personList.add(new Person(\"Lily\", 7800, 21, \"female\", \"Washington\")); personList.add(new Person(\"Anni\", 8200, 24, \"female\", \"New York\")); personList.add(new Person(\"Owen\", 9500, 25, \"male\", \"New York\")); personList.add(new Person(\"Alisa\", 7900, 26, \"female\", \"New York\"));personList.stream().map(salary -> salary.getSalary() + 2000).forEach(System.out::println);

4.1.3 去重、合并(distinct、skip、limit)
 List personList = new ArrayList(); personList.add(new Person(\"Tom\", 8900, 23, \"male\", \"New York\")); personList.add(new Person(\"Jack\", 7000, 25, \"male\", \"Washington\")); personList.add(new Person(\"Lily\", 7800, 21, \"female\", \"Washington\")); personList.add(new Person(\"Anni\", 8200, 24, \"female\", \"New York\")); personList.add(new Person(\"Owen\", 9500, 25, \"male\", \"New York\")); personList.add(new Person(\"Alisa\", 7900, 26, \"female\", \"New York\"));//找出所有的年龄,去重personList.stream().map(Person::getAge).distinct().forEach(System.out::println);// limit:限制从流中获得前3个数据List collect = personList.stream().limit(3).map(Person::getName).collect(Collectors.toList());System.out.println(collect);// skip:跳过前3个数据,从第四个数据开始输出List collect1 = personList.stream().skip(3).map(Person::getName).collect(Collectors.toList());System.out.println(\"==============\");System.out.println(collect1);

4.1.4 合并(concat)
List fruits = Arrays.asList(\"apple\", \"banana\", \"orange\", \"apple\");List integers = Arrays.asList(1, 2, 3, 5);Stream.concat(fruits.stream(), integers.stream()).forEach(System.out::println);


4.2 终结方法

4.2.1收集(collect)

归集(toList、toSet、toMap)

List fruits = Arrays.asList(\"apple\", \"banana\", \"orange\", \"apple\");//方式1:从Stream流收集到List集合List fruitList = fruits.stream().collect(Collectors.toList());System.out.println(fruitList);System.out.println(\"------------------------------------------\");//方式2:从Stream流收集到Set集合Set fruitSet = fruits.stream().collect(Collectors.toSet());System.out.println(fruitSet);System.out.println(\"------------------------------------------\");//方式3:从Stream流收集到Map集合Map fruitMap = fruitSet.stream()  .collect(Collectors.toMap(f -> f, f -> \"fruit\"));System.out.println(fruitMap);

注意:Collectors.toMap(键的规则,值的规则)、并且键不能重复,重复会报错

4.2.2 遍历(forEach)
 List fruits = Arrays.asList(\"apple\", \"banana\", \"orange\", \"apple\"); fruits.stream().forEach(s -> System.out.println(s));

4.2.3 统计(count)
List fruits = Arrays.asList(\"apple\", \"banana\", \"orange\", \"apple\");long count = fruits.stream().count();

4.2.4 收集流中数据放到数组中(toArray)
List fruits = Arrays.asList(\"apple\", \"banana\", \"orange\", \"apple\");String[] strings = fruits.stream().toArray(value -> new String[value]);System.out.println(Arrays.toString(strings));

完美撒花~

也感谢您的点赞对我创作的支持~