0
点赞
收藏
分享

微信扫一扫

stream流

醉倾城1 2022-04-24 阅读 60
java

Stream常用方法
Stream流模型的操作很丰富,这里介绍一些常用的API。这些方法可以被分成两种:


终结方法:返回值类型不再是 Stream 类型的方法,不再支持链式调用。本小节中,终结方法包括 count 和 forEach 方法。

非终结方法:返回值类型仍然是 Stream 类型的方法,支持链式调用。(除了终结方法外,其余方法均为非终结 方法。)

Stream注意事项(重要)
我们学习了Stream的常用方法,我们知道Stream这些常用方法可以分成两类,终结方法,函数拼接方法

Stream的3个注意事项:

Stream只能操作一次

Stream方法返回的是新的流

Stream不调用终结方法,中间的操作不会执行

集合处理数据的弊端
当我们需要对集合中的元素进行操作的时候,除了必需的添加、删除、获取外,最典型的就是集合遍历。我们来体验 集合操作数据的弊端,需求如下:

一个ArrayList集合中存储有以下数据:

张无忌,周芷若,赵敏,张强,张三丰

需求:

1.拿到所有姓张的

2.拿到名字长度为3个字的

3.打印这些数据

代码如下:

public static void main(String[] args) {
   // 一个ArrayList集合中存储有以下数据:张无忌,周芷若,赵敏,张强,张三丰
   // 需求:1.拿到所有姓张的 2.拿到名字长度为3个字的 3.打印这些数据
   ArrayList<String> list = new ArrayList<>();
   Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张强", "张三丰");
   // 1.拿到所有姓张的
   ArrayList<String> zhangList = new ArrayList<>(); // {"张无忌", "张强", "张三丰"}
   for (String name : list) {
    if (name.startsWith("张")) {
      zhangList.add(name);
    }
}
   // 2.拿到名字长度为3个字的
   ArrayList<String> threeList = new ArrayList<>(); // {"张无忌", "张三丰"}
   for (String name : zhangList) {
     if (name.length() == 3) {
      threeList.add(name);
    }
   }
   // 3.打印这些数据
   for (String name : threeList) {
     System.out.println(name);
   }
}
循环遍历的弊端

这段代码中含有三个循环,每一个作用不同:

首先筛选所有姓张的人;

然后筛选名字有三个字的人;

最后进行对结果进行打印输出。

每当我们需要对集合中的元素进行操作的时候,总是需要进行循环、循环、再循环。这是理所当然的么?不是。循环 是做事情的方式,而不是目的。每个需求都要循环一次,还要搞一个新集合来装数据,如果希望再次遍历,只能再使 用另一个循环从头开始。

那Stream能给我们带来怎样更加优雅的写法呢?

Stream的更优写法

下面来看一下借助Java 8的Stream API,修改后的代码:

public class Demo03StreamFilter {
public static void main(String[] args) {
   List<String> list = new ArrayList<>();
       list.add("张无忌");
       list.add("周芷若");
       list.add("赵敏");
       list.add("张强");
       list.add("张三丰");
       list.stream()
                   .filter(s -> s.startsWith("张"))
                   .filter(s -> s.length() == 3)
                   .forEach(System.out::println);
   }
}
直接阅读代码的字面意思即可完美展示无关逻辑方式的语义:获取流、过滤姓张、过滤长度为3、逐一打印。我们真 正要做的事情内容被更好地体现在代码中。

Stream流式思想概述
注意:Stream和IO流(InputStream/OutputStream)没有任何关系,请暂时忘记对传统IO流的固有印象!

Stream流式思想类似于工厂车间的“生产流水线”,Stream流不是一种数据结构,不保存数据,而是对数据进行加工 处理。Stream可以看作是流水线上的一个工序。在流水线上,通过多个工序让一个原材料加工成一个商品。

Stream API能让我们快速完成许多复杂的操作,如筛选、切片、映射、查找、去除重复,统计,匹配和归约。

小结

首先我们了解了集合操作数据的弊端,每次都需要循环遍历,还要创建新集合,很麻烦 Stream是流式思想,相当于工厂的流水线,对集合中的数据进行加工处理

Stream流的forEach方法
forEach 用来遍历流中的数据

void forEach(Consumer<? super T> action);

该方法接收一个 Consumer 接口函数,会将每一个流元素交给该函数进行处理。例如:

@Test
public void testForEach() {

   List<String> one = new ArrayList<>();
   Collections.addAll(one, "迪丽热巴", "宋远桥", "苏星河", "老子", "庄子", "孙子");

   /*one.stream().forEach((String s) -> {
   System.out.println(s);
   });*/

   // 简写
   // one.stream().forEach(s -> System.out.println(s));
   one.stream().forEach(System.out::println);
}
Stream流的count方法

Stream流提供 count 方法来统计其中的元素个数:

long count();

该方法返回一个long值代表元素个数。基本使用:

@Test
public void testCount() {
   List<String> one = new ArrayList<>();
   Collections.addAll(one, "迪丽热巴", "宋远桥", "苏星河", "老子", "庄子", "孙子");
   System.out.println(one.stream().count());
}
Stream流的filter方法

filter用于过滤数据,返回符合过滤条件的数据

可以通过 filter 方法将一个流转换成另一个子集流。方法声明:

Stream<T> filter(Predicate<? super T> predicate);

该接口接收一个 Predicate 函数式接口参数(可以是一个Lambda或方法引用)作为筛选条件。

Stream流中的 filter 方法基本使用的代码如:

@Test
public void testFilter() {

   List<String> one = new ArrayList<>();
   Collections.addAll(one, "迪丽热巴", "宋远桥", "苏星河", "老子", "庄子", "孙子");

   one.stream().filter(s -> s.length() == 2).forEach(System.out::println);
}


在这里通过Lambda表达式来指定了筛选的条件:姓名长度为2个字。

Stream流的limit方法


limit 方法可以对流进行截取,只取用前n个。方法签名:

Stream<T> limit(long maxSize);

参数是一个long型,如果集合当前长度大于参数则进行截取。否则不进行操作。基本使用:

@Test
public void testLimit() {
List<String> one = new ArrayList<>();
   Collections.addAll(one, "迪丽热巴", "宋远桥", "苏星河", "老子", "庄子", "孙子");
   one.stream().limit(3).forEach(System.out::println);
}


Stream流的skip方法


如果希望跳过前几个元素,可以使用 skip 方法获取一个截取之后的新流:

Stream<T> skip(long n);

如果流的当前长度大于n,则跳过前n个;否则将会得到一个长度为0的空流。基本使用:

@Test
public void testSkip() {
   List<String> one = new ArrayList<>();
   Collections.addAll(one, "迪丽热巴", "宋远桥", "苏星河", "老子", "庄子", "孙子");
   one.stream().skip(2).forEach(System.out::println);
}
Stream流的map方法

如果需要将流中的元素映射到另一个流中,可以使用 map 方法。方法签名:

<R> Stream<R> map(Function<? super T, ? extends R> mapper);

该接口需要一个 Function 函数式接口参数,可以将当前流中的T类型数据转换为另一种R类型的流。

Stream流中的 map 方法基本使用的代码如:

@Test
public void testMap() {
   Stream<String> original = Stream.of("11", "22", "33");
   Stream<Integer> result = original.map(Integer::parseInt);
   result.forEach(s -> System.out.println(s + 10));
}


这段代码中, map 方法的参数通过方法引用,将字符串类型转换成为了int类型(并自动装箱为 Integer 类对象)。 作者:木子教程 https://www.bilibili.com/read/cv14222552 出处:bilibili

举报

相关推荐

Stream流

Stream流(Java)

Stream流编程

Stream流常用

Java | Stream流

Stream流学习

0 条评论