Java8新特性之——Stream API

一、简介

JDK 8 引入了 Stream API,它是用于处理集合数据的功能强大的库。Stream API 提供了一种更为简洁、灵活和函数式的方式来进行集合的操作和处理。

Stream API 有三大特性:

  • 不存储数据:Stream API 并不会在内存中存储数据,它仅仅是对源数据进行操作和处理的管道,当我们对一个集合或数组创建流时,流只是作为一种处理方式存在,并没有实际保存数据。
  • 不改变源数据:Stream API 的操作不会改变原始数据源中的元素,所有的中间操作(如过滤、映射、排序)都会产生一个新的流,而不是直接修改原始数据。这种特性确保了数据的不可变性。
  • 延时执行:Stream API 使用了延迟执行的概念。它并不会立即执行流的操作,而是等到需要结果时才进行计算。这样可以避免不必要的计算,提高效率并节省资源。只有在终端操作(如聚合、收集、计数)被调用时,流才会进行实际的计算。

二、操作分类

在使用 Stream API 进行集合操作时,一般会遵循以下步骤:

  1. 创建流:通过集合或数组创建一个流
  2. 中间操作:对流进行一系列的中间操作,例如过滤、映射、排序等。这些操作可以按照需求进行链式调用
  3. 结束操作:中间操作只是一种标记,只有结束操作才会触发实际计算

其中中间操作又分为,无状态和有状态,结束操作又分为短路操作和非短路操作

image-20230825170946157

创建流

通过集合

可以使用 Collection 接口中的 stream() 方法或者 parallelStream() 方法来创建一个流

List<String> list = Arrays.asList("a", "b", "c");
Stream<String> stream = list.stream();

通过数组

可以使用 Arrays 类中的静态方法 stream() 来创建一个数组的流

String[] array = {"a", "b", "c"};
Stream<String> stream = Arrays.stream(array);

通过Stream的of()方法

可以使用 Stream 类中的静态方法 of() 来根据指定的元素创建一个流

Stream<String> stream = Stream.of("a", "b", "c");

中间操作

无状态

元素的处理不受前一个元素影响

  • filter(过滤):接收一个 Predicate 参数,根据 Predicate 的判断结果决定是否保留流中的元素, true 留下,false 丢弃
  • map、mapToInt、mapToLong、mapToDouble(转换):map 方法接收一个 Function 参数,将流中的每个元素通过该函数进行转换,mapToInt、mapToLong、mapToDouble 和 map 差不多,只是强制指定了返回值必须是 int、long、double 类型
  • flatMap、flatMapToInt、flatMapToLong、flatMapToDouble(合并):将一个或多个流合并成一个新流,flatMapToInt、flatMapToLong、flatMapToDouble 和 f latMap 差不多,只是返回的是对应的 IntStream、LongStream、DoubleStream 流
  • peek(监测):接受一个Consumer 函数作为参数,该函数会在流的每个元素被处理时被调用。它可以用于在处理流的过程中观察每个元素的值,而不会改变流的内容
//filter
public static void main(String[] args) {
    String[] str = {"a", "b", "c"};
    Stream.of(str).filter(t -> t.equals("a")).forEach(System.out::println);
    //输出
    //a
}

//map、mapToInt、mapToLong、mapToDouble
public static void main(String[] args) {
    String[] str = {"a", "b", "c"};
    Stream.of(str).map(t -> t.toUpperCase()).forEach(System.out::println);
    Stream.of(str).mapToInt(t -> t.hashCode()).forEach(System.out::println);
    //输出
    //A
    //B
    //C
    //97
    //98
    //99
}

//flatMap、flatMapToInt、flatMapToLong、flatMapToDouble
public static void main(String[] args) {
    List<String> a = new ArrayList<>();
    a.add("a");
    a.add("b");
    List<String> b = new ArrayList<>();
    b.add("c");
    b.add("d");
    Stream.of(a, b).flatMap(u -> u.stream()).forEach(System.out::println);
    //输出
    //a
    //b
    //c
    //d
}

//peek
public static void main(String[] args) {
    String[] str = {"a", "b", "c"};
    Stream.of(str).peek(t -> System.out.println("this is " + t)).collect(Collectors.toList());
    //输出
    //this is a
    //this is b
    //this is c
}

有状态

必须等所有元素处理完毕之后才知道最终的结果

  • distinct(去重):去除重复的元素
  • sorted(排序):不传参数,会按照自然排序,也可以传一个比较器参数,会根据比较器定义的顺序排序
  • limit(限制):截取前n个元素
  • skip(跳过):跳过n个元素,返回之后的元素
//distinct
public static void main(String[] args) {
    String[] str = {"a", "a", "b", "b", "c"};
    Stream.of(str).distinct().forEach(System.out::println);
    //输出
    //a
    //b
    //c
}

//sorted
public static void main(String[] args) {
    String[] str = {"banana", "apple", "pineapple", "pear", "watermelon"};
    Stream.of(str).sorted().forEach(System.out::println);
    System.out.println("---------------");
    Stream.of(str).sorted(Comparator.comparing(String::length)).forEach(System.out::println);
    //输出
    //apple
    //banana
    //pear
    //pineapple
    //watermelon
    //---------------
    //pear
    //apple
    //banana
    //pineapple
    //watermelon
}

//limit
public static void main(String[] args) {
    String[] str = {"a", "b", "c", "d", "e"};
    Stream.of(str).limit(2).forEach(System.out::println);
    //输出
    //a
    //b
}

//skip
public static void main(String[] args) {
    String[] str = {"a", "b", "c", "d", "e"};
    Stream.of(str).skip(2).forEach(System.out::println);
    //输出
    //c
    //d
    //e
}

结束操作

非短路操作

需要处理完所有元素

  • forEach(循环):循环操作Stream中数据
  • forEachOrdered(排序循环):按照流的遭遇顺序来处理元素,在并行流中使用
  • toArray(转数组):不传参数的话,返回的是对象数组,也可以接收一个 IntFunction<A[]> generator 参数来指定返回数据的类型
  • reduce(聚合):聚合操作,一般用来做统计
  • collect(收集):将元素收集到一个集合或其他数据结构里
  • min(最小值):根据传入的比较器,找到最小的元素
  • max(最大值):根据传入的比较器,找到最大的元素
  • count(总数量):计数,统计元素数量
//forEach
public static void main(String[] args) {
    String[] str = {"a", "b", "c"};
    Stream.of(str).forEach(System.out::println);
    //输出
    //a
    //b
    //c
}

//toArray
public static void main(String[] args) {
    String[] str = {"1", "2", "3"};
    Object[] objectArray = Stream.of(str).toArray();
    String[] strArray = Stream.of(str).toArray(String[]::new);
}

//reduce
public static void main(String[] args) {
    Integer[] array = {1, 2, 3, 4, 5};
    Optional<Integer> optional = Stream.of(array).reduce((x, y) -> x + y);
    optional.ifPresent(System.out::println);
    //输出
    //15
}

//collect
public static void main(String[] args) {
    Integer[] array = {1, 2, 3, 4, 5};
    List<Integer> list = Stream.of(array).collect(Collectors.toList());
    System.out.println(list);
    //输出
    //[1, 2, 3, 4, 5]
}

//min
public static void main(String[] args) {
    Integer[] array = {1, 2, 3, 4, 5};
    Optional<Integer> min = Stream.of(array).min(Comparator.comparing(Integer::intValue));
    min.ifPresent(System.out::println);
    //输出
    //1
}

//max
public static void main(String[] args) {
    Integer[] array = {1, 2, 3, 4, 5};
    Optional<Integer> max = Stream.of(array).max(Comparator.comparing(Integer::intValue));
    max.ifPresent(System.out::println);
    //输出
    //5
}

//count
public static void main(String[] args) {
    String[] str = {"a", "b", "c"};
    long count = Stream.of(str).count();
    System.out.println(count);
    //输出
    //3
}

短路操作

一旦满足或不满足条件,就结束计算,不用处理完所有元素

  • anyMatch:只要有一个符合条件就返回 true
  • allMatch:所有都符合条件返回 true
  • noneMatch:所有数据都不符合条件返回true
  • findFirst:获取第一个元素
  • findAny:获取任一元素,一般用于并行流
//anyMatch
public static void main(String[] args) {
    String[] str = {"banana", "apple", "pineapple", "pear", "watermelon"};
    boolean b = Stream.of(str).anyMatch(t -> t.length() == 4);
    boolean b2 = Stream.of(str).anyMatch(t -> t.length() == 3);
    System.out.println(b);
    System.out.println(b2);
    //输出
    //true
    //false
}

//allMatch
public static void main(String[] args) {
    String[] str = {"banana", "apple", "pineapple", "pear", "watermelon"};
    boolean b = Stream.of(str).allMatch(t -> t.length() >= 4);
    boolean b2 = Stream.of(str).allMatch(t -> t.length() >= 5);
    System.out.println(b);
    System.out.println(b2);
    //输出
    //true
    //false
}

//noneMatch
public static void main(String[] args) {
    String[] str = {"banana", "apple", "pineapple", "pear", "watermelon"};
    boolean b = Stream.of(str).noneMatch(t -> t.length() >= 4);
    boolean b2 = Stream.of(str).noneMatch(t -> t.length() <= 3);
    System.out.println(b);
    System.out.println(b2);
    //输出
    //false
    //true
}

//findFirst
public static void main(String[] args) {
    String[] str = {"banana", "apple", "pineapple", "pear", "watermelon"};
    Optional<String> first = Stream.of(str).findFirst();
    first.ifPresent(System.out::println);
    //输出
    //banana
}

//findAny
public static void main(String[] args) {
    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
    numbers.parallelStream()
        .filter(n -> n % 2 == 0)
        .findAny().ifPresent(System.out::println);
    //输出
    //2 or 4
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

每天进步亿点点的小码农

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值