Java8流式操作

本文介绍了Java8中新增的流式操作功能,演示了如何在数组和集合上使用流进行过滤、排序、汇总等函数式操作,并展示了并行运算的能力。通过两个实例详细解释了流的操作过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java8中提供了java.util.stream包,使用这个包可以进行流式操作(stream)。流式操作是Java语言非常具有革命性的改变,它使得在数组及集合上进行函数式操作(如过滤、排序、汇总等)成为可能,而且这些操作可以并行的进行。函数式操作、并行运算这两个特点是适应了计算领域的最新发展。

使用流的基本方法

流是指能够进行串行或并列函数式操作的一系列元素。使用流要经过两个步骤,首先你需要获得流,然后就是操作流。

你可以在数组或者集合上获得流,有以下4种情况:

  1. 在数组上获得流:Arrays.stream()
  2. 在数组上获得并行处理流:Arrays.stream.parallel()
  3. 在集合(Collection,包括Set,List)上获得流:collection.stream()
  4. 在集合上获得并行流:collection.parallelStream()

获得的流对象是已实现java.util.stream.Stream接口的对象,其上可以进行一系列的操作,包括过滤、求和等等。

可以看一个例子:

import java.util.Arrays;
import java.util.OptionalInt;

public class streamExcise {
    public static void main(String[] args) {
        int[] array = new int[100];
        for (int i=0;i<array.length;i++)
            array[i] = i;
        OptionalInt result = Arrays.stream(array).parallel()
                .filter(i->i>20)	// 过滤,条件是大于20
                .map(i->i*i)		// 映射,得到数组中每个数的平方
                .sorted()			// 排序
                .distinct()			// 去掉重复元素
                .limit(10)			// 取其中前10个元素
                .max();				// 求出当前数组的最大值
        System.out.println(result.isPresent()?"最大值为"+result.getAsInt():"无值");
    }
}

其中OptionalInt是一个可能有值得整数,也可能没有值。通过isPresent()判断是否有值,使用getAsInt()得到其中得值。

这段程序输出结果是最大值为900

另一个例子,对集合使用流:

public class streamList {
    public static void main(String[] args) {
        Collection <Person> people = Arrays.asList(
                new Person("Ted",18,88),
                new Person("Charlotte",18,88),
                new Person("Michael",18,99),
                new Person("Matthew",19,84),
                new Person("Matthew",21,84)
        );
        OptionalDouble result = people.parallelStream()
                .filter(p->p.age>20)
                .sorted(Person::better)
                .sorted(Comparator.comparing(Person::getName))
                .limit(5)
                .mapToDouble(p->p.score)
                .average();
        System.out.println(result);
    }
}
class Person {
    String name;
    int age;
    double score;
    Person(String name, int age, double score) {
        this.name = name;
        this.age = age;
        this.score= score;
    }
    public String getName() {
        return name;
    }
    public String toString() {
        return String.format("%s[%d](%f)",name,age,score);
    }
    public static int better(Person p1, Person p2) {
        return (int)(p2.score-p1.score);
    }
}

流及操作的种类

流的种类

Stream是普通的流,它的子接口还有以下几种:

  1. IntStream:整数的流。
  2. LongStream:长整数的流。
  3. DoubleStream:实数的流。

对于普通的Stream可以通过mapToInt()、mapToLong()、mapToDouble()来转换成相应的流。

流式操作

流式操作既可以是中间的(intermediate opeartion)也可以是末端的(terminal operation)

中间的流操作保持流为打开状态,并允许后续的操作,当一个末端操作被调用的时候,流会被消耗并且不再可用。需要注意的是,流式操作一定要以末端操作结尾。不然编译器会报异常。

常见中间操作如下:

操作作用
filter按照给定条件过滤元素
map将元素按照给定条件就进行映射
flatMap将每个元素转变为无或更多的元素
peek对每个遇到的元素执行一些操作
distinct根据.equals行为排除所有重复的元素
sorted将流中元素排序,确保后续操作按照此顺序进行
limit保证后续的操作所能看到的最大数量的元素
substream确保后续的操作只能看到一个范围的元素
skip忽略一些元素
mapToDouble、mapToInt、mapToLong类型转换

常见的末端操作如下:

操作作用
forEach对流中的每个元素执行一些操作
toArray对流中的元素倾倒入一个数组
min根据一个比较器找到流中元素的最小值
max根据一个比较器找到流中元素的最大值
count计算流中元素的数量
anyMatch判断流中是否至少有一个元素都匹配断言
allMatch判断流中是否每一个元素都匹配断言
noneMatch判断流中是否没有一个元素匹配断言
findFirst查找流中的第一个元素
findAny查找流中的任意元素

对于流的子接口如IntStream,LongStream,DoubleStream还有更多的操作,如sum求和、average求平均值、summaryStatistics进行统计等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阳寜

“请作者吃颗糖!”

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值