首页 > 其他分享 > Stream流(JDK8)

Stream流(JDK8)

时间:2023-02-11 20:32:30浏览次数:50  
标签:Stream stream 元素 list add JDK8 方法

Stream流为JDK8新增特性,为数组、集合等批量数据提供了一套函数式操作方法,简化数组和集合操作的API。

这个Stream的流不同于​java.io​的InputStreamOutputStream,它代表的是任意Java对象的序列。

一个顺序输出的Java对象序列,不就是一个List容器吗?

这个StreamList也不一样,List存储的每个元素都是已经存储在内存中的某个Java对象,而Stream输出的元素可能并没有预先存储在内存中,而是实时计算出来的。

Stream的工作原理

一个​​Stream​​可以轻易地转换为另一个​​Stream​​,而不是修改原​​Stream​​本身。最后,真正的计算通常发生在最后结果的获取,也就是惰性计算(一个​​Stream​​转换为另一个​​Stream​​时,实际上只存储了转换规则,并没有任何计算发生)。例如:

Stream<BigInteger> naturals = createNaturalStream(); // 不计算
Stream<BigInteger> s2 = naturals.map(BigInteger::multiply); // 不计算
Stream<BigInteger> s3 = s2.limit(100); // 不计算
s3.forEach(System.out::println); // 计算

创建一个全体自然数的​​Stream​​,不会进行计算,把它转换为上述​​s2​​这个​​Stream​​,也不会进行计算。再把​​s2​​这个无限​​Stream​​转换为​​s3​​这个有限的​​Stream​​,也不会进行计算。只有最后,调用​​forEach​​确实需要​​Stream​​输出的元素时,才进行计算。

Stream流的三类方法

  1. 起始方法:获取Stream流
  2. 中间方法:返回的是Stream流,所以能继续调用Stream流方法,都能支持链式编程
  3. 终结方法:调用终结方法后就无法使用该Stream流

获取Steam流

  1. 集合获取Stream流的主要方式是Collection接口中默认方法:​​stream()​​、​​parallelStream()​
  2. 数组获取Stream流主要是靠Arrays工具类的​​stream()​​、Stream类的​​of()​

stream()

/**
* default Stream<E> stream()
* 返回以此集合作为其源的Stream流
*/
Collection<Integer> list = new ArrayList<>();
Stream<Integer> stream = list.stream();

parallelStream()

/**
* default Stream<E> parallelStream()
* 提供了流的并行处理,其底层使用Fork/Join框架实现。
*/
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
numbers.parallelStream().forEach(num ->
System.out.println(Thread.currentThread().getName() + ">>" + num));
  • 串行流:适合存在线程安全问题、阻塞任务、重量级任务,以及需要使用同一事务的逻辑。
  • 并行流:适合没有线程安全问题、较单纯的数据处理任务。

Map没有不是继承自Collection接口,因此没有这两种方法

Arrays.stream()

Arrays工具类的stream方法

/**
* public static <T> Stream<T> stream(T[] array)
* 返回以指定数组作为其源的Stream流
*/
int[] arr = new int[10];
IntStream stream = Arrays.stream(arr);

Stream.of()

Stream接口的of方法:

/**
* static <T> Stream<T> of(T... values)
* 返回元素为指定值的顺序有序流
*/
Stream<Integer> stream = Stream.of(1, 3, 5, 9, 7, 23);

其底层其实还是调用的Arrays.stream

public static<T> Stream<T> of(T... values) {
return Arrays.stream(values);
}

其他方法

  1. 传入​​Supplier​​,调用​​Stream.generate()​​获取Stream流
  2. ​Files​​类的​​lines()​​方法:把一个文件变成一个​​Stream​​,每个元素代表文件的一行内容
  3. ​Pattern​​类的​​splitAsStream()​​方法:把一个长字符串分割成​​Stream​​序列而不是数组

具体使用见此:​​创建Stream - 廖雪峰的官方网站 (liaoxuefeng.com)​

处理Stream流

方法

描述

filter(Predicate<? super T> predicate)

用于对流中的数据进行过滤

limit(long maxSize)

获取前几个元素

skip(long n)

跳过前n个元素

distinct()

去除流中重复的元素。依赖(hashCode和equals方法)

concat(Stream a, Stream b)

合并流a和流b。当合并不同类型的流,比如String和Integer,可以使用Object来接收

map()

转换流

sorted([Comparator])

排序,可选择提供比较器

map()

所谓​​map​​操作,就是把一种操作运算,映射到一个序列的每一个元素上。例如,对​​x​​计算它的平方,可以使用函数 Stream流(JDK8)_List。我们把这个函数映射到一个序列1,2,3,4,5上,就得到了另一个序列1,4,9,16,25

Stream<Integer> s1 = Stream.of(1, 2, 3, 4, 5);
Stream<Integer> s2 = s1.map(n -> n * n);

利用​​map()​​,不但能完成数学计算,对于字符串操作,以及任何Java对象都是非常有用的。

List.of("  Apple ", " pear ", " ORANGE", " BaNaNa ") // 获取List
.stream() // 转化Stream
.map(String::trim) // 去空格
.map(String::toLowerCase) // 变小写
.forEach(System.out::println); // 打印

工作原理:

​map()​​方法接收的对象是​​Function​​接口对象,它定义了一个​​apply()​​方法,负责把一个​​T​​类型转换成​​R​​类型

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

​Function​​的定义是:

@FunctionalInterface
public interface Function<T, R> {
// 将T类型转换为R:
R apply(T t);
int Worlda;
}

filter()

对一个​​Stream​​的所有元素一一进行测试,不满足条件的就被“滤掉”了,剩下的满足条件的元素就构成了一个新的​​Stream​​。如下:

IntStream.of(1, 2, 3, 4, 5, 6, 7, 8, 9)
.filter(n -> n % 2 != 0)
.forEach(System.out::println);

工作原理:

​filter()​​方法接收的对象是​​Predicate​​接口对象,它定义了一个​​test()​​方法,负责判断元素是否符合条件。

@FunctionalInterface
public interface Predicate<T> {
// 判断元素t是否符合条件:
boolean test(T t);
}

结束Stream流

方法

描述

void forEach(Consumer<? super T> action)

遍历,对此流的每个元素执行操作。

long count()

返回此流的元素数

终结操作方法,调用完成后流就无法继续使用了,原因是不会返回Stream了。

reduce()

把一个​​Stream​​的所有元素按照聚合函数聚合成一个结果。

// 求和
int sum = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9).reduce(0, (acc, n) -> acc + n);
System.out.println(sum); // 45

// 求积
int s = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9).reduce(1, (acc, n) -> acc * n);
System.out.println(s); // 362880

工作原理:

​reduce()​​方法传入的对象是​​BinaryOperator​​接口,它定义了一个​​apply()​​方法,负责把上次累加的结果和本次的元素 进行运算,并返回累加的结果。

@FunctionalInterface
public interface BinaryOperator<T> {
// 两个输入,一个输出
T apply(T t, T u); // apply(初始值,循环操作)
}

collect()

把​​Stream​​操作后的结果数据收集到一个集合中。

方法

描述

collect(Collector collector)

开始收集Stream流,指定收集器。

Collectors类 提供了具体的收集方式:

方法

描述

Collector toList()

把元素收集到List集合中

Collector toSet()

把元素收集到Set集合中

toMap(Function keyMapper , Function valueMapper)

把元素收集到Map集合中

public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
list.add(6);
list.add(3);
list.add(1);
list.add(-2);
list.add(7);
Stream<Integer> stream = list.stream();
List<Integer> objects = stream.sorted().collect(Collectors.toList());
for (Integer object : objects) {
System.out.println(object);
}
}

toArray()

把​​Stream​​操作后的结果数据收集到一个数组中。

方法

描述

Object[] toArray()

将流收集到Object类数组

​<A>​​ A[] toArray(IntFunction<A[]> generator)

将流收集到指定类型的数组

public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
list.add(6);
list.add(3);
list.add(1);
list.add(-2);
list.add(7);
Stream<Integer> stream = list.stream();
Object[] objects = stream.sorted((o1, o2) -> -(o1 - o2)).toArray();
System.out.println(Arrays.toString(objects));
}

流只能使用一次,也就是收集过后无法再次收集。

标签:Stream,stream,元素,list,add,JDK8,方法
From: https://blog.51cto.com/u_15936519/6050952

相关文章

  • Ubuntu 的源相关介绍(最近在配gstreamer的时候,紧急补充的知识)
    PS:要转载请注明出处,本人版权所有。PS:这个只是基于《我自己》的理解,如果和你的原则及想法相冲突,请谅解,勿喷。前置说明  本文作为本人csdnblog的主站的备份。(BlogID......
  • Stream流
    体验Stream流Stream流一般配合Lamda表达式使用函数式编程通过字面意思即可展示无关逻辑的语句publicclassDemo{publicstaticvoidmain(String[]args)......
  • JAVA8之Stream(其一:分页)
    分页,是项目开发中的常驻者,想必大家都使用过PageHelper进行分页,或者利用mysql语句的limit进行分页。利用PageHelper去分页,无非就是在你的sql语句外层嵌套一个limit,一旦遇到......
  • upstream和proxy模块
    nginx负载均衡-upstream和proxy模块(1)Cloud研习社 Cloud研习社 2023-01-1007:31 发表于北京收录于合集#一站式教程195个#云计算148个#计算机137个#nginx37......
  • Java FileInputStream/FileOutputStream的应用 文件读取和写入//京鸿通信科技//www.ky
    这是一对继承于InputStream和OutputStream的类,用于本地文件读写(二进制格式读写并且是顺序读写,读和写要分别创建出不同的文件流对象);本地文件读写编程的基本过程为:① 生......
  • JDK8 新语法介绍(Lambda、Stream、Optional)
    (目录)lambda表达式代码中的遇到的函数式接口(有且仅有一个抽象方法),可以用lambda来代替,比如MQ发消息,我们传统的做法:jmsTemplate.send(newMessageCreator(){......
  • npmFix the upstream dependency conflict, or retry npm ERR! this command with --f
      因为node7在某些事件处理上比node6更加严格,解读上面的报错信息,找到解决方案npminstall--legacy-peer-deps即可成功安装node_modules ......
  • java8排序stream().sorted()
    默认升序 先以年龄升序排序年龄相同是按分数降序List<Student>list=userList.stream().sorted(Comparator.comparing(Student::getAge).thenComparing(Student::g......
  • java-Stream流的常用方法
    一 常见创建流的三种方式//list集合创建流方式newArrayList<>().stream();newHashSet<>().stream();//map集合创建流方式,原......
  • JDK8 Stream的使用
    借助Lambda表达式,可以简化集合类的操作。一、List 二、Set三、Map四、Array ......