Java进阶之路 java8 流库

本文介绍了Java8中的流库,包括流的概念、优点、创建方法、转换操作、子流和组合流的抽取,重点讲解了约简操作如count、max/min,Optional类的使用,以及基本类型流和并行流的应用。通过使用流,代码可读性增强,且能实现并行计算,提升处理效率。
摘要由CSDN通过智能技术生成

Java进阶之路 java8 流库

java8 API中文文档链接

在处理集合时,当我们需要遍历集合中元素,或者需要在每个元素时进行操作。列如,假设我们想要对某本书中的所有长单词进行计数。可以通过

var contents = new String(Files.readAllBytes(Paths.get("E:/1program/words.txt")),StandardCharsets.UTF_8);  //从文件中读取数据
List<String> words = List.of(contents.split("\\PL+"));  //通过正则表达式将其单词分为一个个字符串
int count = 0;  
for (String w : words){
   
    if(w.length() > 12)count++;  //计数
}

在使用流之后,相同的操作看起来像下面这样:

var contents = new String(Files.readAllBytes(Paths.get("E:/1program/words.txt")),StandardCharsets.UTF_8);  //从文件中读取数据
List<String> words = List.of(contents.split("\\PL+"));  //通过正则表达式将其单词分为一个个字符串
long count = words.stream()  //将list转化为流
        .filter(w -> w.length() > 12) //lambda表达式
        .count(); //计数

新的操作可读性很强,可以直接通过方法名确定这段代码意欲何为。此外,将stream()修改为parallelStream()可以并行的方式来执行过滤和计数。

long count = words.parallelStream()  
        .filter(w -> w.length() > 12) 
        .count(); 

一,流是什么

流是一类数据项,是一种可以让我们在更高的概念级别上指定计算任务的数据视图。

二,流的优点

流遵循了“做什么而非怎么做”的原则,它主要是对集合进行处理,它与集合相似,却有着显著的差异。
1,流并不储存元素。这些元素可能储存在底层的集合中,或者是按需生成的。
2,流的操作不会修改其数据源。当需要对数据进行处理时,会生成一个新的流包含修改后的元素。
3,流的操作是尽可能惰性执行的。这意味着直至需要其结果时,操作才会执行。

三,流的创建

1,通过Collection接口的stream方法将集合转化为一个流。

// default Stream<E> stream()
// default Stream<E> parallelStream()
// 产生当前集合中所有元素的顺序流或并行流
var contents = new String(Files.readAllBytes(Paths.get("E:/1program/words.txt")),StandardCharsets.UTF_8);  //从文件中读取数据
List<String> words = List.of(contents.split("\\PL+"));
Stream<String> stream1 = words.stream();
Stream<String> stream2 = words.stream();
//还可以通过Array.stream(array, from, to) 可以用数组中的一部分元素来创建一个流。

2,通过静态的Stream.of方法。

//static <T> Stream<T> of(T... values>
//产生一个元素为定值的流。
var contents = new String(Files.readAllBytes(Paths.get("E:/1program/words.txt")),StandardCharsets.UTF_8);
Stream<String> stream = Stream.of(contents.split("\\PL+")); //split方法返回的为一个String数组

//of方法具有可变长参数,因此我们可以构建具有任意数量引元的流;
Stream<String> stream = Stream.of("gently", "down", "the", "stream");

3,通过Stream.empty方法。

//static <T> Stream<T> empty()
//产生一个不包含任何元素的流
Stream<String> stream = Stream.empty();

4,通过Stream.generate方法。

//static <T> Stream<T> generate(Supplier<T> s)
//产生一个无限流,它的值是通过反复调用函数s而构建的
Stream<String> stream1 = Stream.generate(() -> "Echo");
Stream<Double> stream2 = Stream.generate(Math::random);
//generate方法接受一个不包含任何引元的函数(及java8 函数式接口 Supplier<T>接口的对象)

5,通过Stream.iterate方法。

//static <T> Stream<T> iterate(T seed, UnaryOperator<T> f)
//static <T> Stream<T> iterate(T seed, Predicate<? super T> hasNext, UnaryOperator<T> f)
//产生一个无限流,他的元素包含 seed,在 seed上调用f产生的值,在前一个元素上调用f产生的值,等等。第一个方法会产生一个无限流,而第二个方法产生的流会在碰到第一个不满足hasNext的元素时终止。
Stream<BigInteger> integers = Stream.iterate(BigInteger.ZERO, n -> n.add(BigInteger.ONE));
//该序列中的一个元素时种子BigInteger.ZERO,第二个元素时f(seed),即1,下一个元素时f(f(seed)),即2,后续以此类推。
var limit = new BigInteger("100000");
Stream<BigInteger> stream = Stream.iterate(BigInteger.ZERO, n -> n.compareTo(limit) < 0, n -> n.add(BigInteger.ONE));
//第二个加了一个限制条件,n的最大值。

6,通过Stream.ofNullable方法。

//static <T> Stream<T> ofNummable(T t)
//如果t为null,返回一个空流,否则返回包含t的流。
var contents = new String(Files.readAllBytes(Paths.get("E:/1program/words.txt")),StandardCharsets.UTF_8);
Stream<String> stream1 = Stream.ofNullable(contents);
Stream<String> stream2 = Stream.ofNullable(null);

7,通过迭代器Spliterator的spliteratorUnknownSize方法

//static <T> Spliterator<T> spliteratorUnknownSize(Iterator<? extends T> iterator, int characteristics)
//用于给定的特性(一种包含诸如Spliterator.ORDERED之类的常量的位模式)将一个迭代器转换为一个具有未知尺寸可分割的迭代器。
Iterator<Path> iterator = Paths.get("E:/1program/words.txt").iterator()
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值