Java中Stream流的相关使用案列

前言

该案例是自己根据网上相关资料整理的一些项目中可能会用到的Stream流的操作相关内容,项目中我会慢慢养成这种习惯的,可以很大程度的提高开发效率

代码

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 用于演示java8中Stream流的相关内容
 * 注意:
 * ①Stream操作符中与Collectors.中类似的收集器功能,如果能用Steam的操作符就去使用,这样可以降低系统开销
 * ②在整个流的操作过程中,终止操作符只能使用一次,用作收尾。forEach除外,因为foreach只是一个语法糖
 *
 * @author wyj
 * @date 2021/5/14 9:21
 */
public class MyStream {

  public static void main(String[] args) {
    collectOperator();
  }

  /** *终止操作符,collect的收集器详解 */
  public static void collectOperator() {
    // collect 收集: 使用系统提供的收集器可以将最终的数据流收集到List,Set,Map等容器中
    User user = new User(1L, 1L, "老大");
    User user1 = new User(2L, 1L, "老二");
    User user2 = new User(3L, 2L, "老三");
    User user3 = new User(4L, 2L, "老三");
    // Collectors.toSet()将数据收集到Set集合,可自行去重
    Stream.of(user, user1, user2).collect(Collectors.toSet()).forEach(System.out::println);
    // Collectors.toList()将数据收集到ArrayList集合
    Stream.of(user, user1, user2).collect(Collectors.toList()).forEach(System.out::println);
    Stream.of(user, user1, user2)
        .collect(Collectors.toCollection(ArrayList::new))
        .forEach(System.out::println);

    /*
     * Collectors.toList():将流中的元素转换到一个Map中,需要指定key和value
     */
    // id作为key,name作为value
    Map<Long, String> collect =
        Stream.of(user, user1, user2).collect(Collectors.toMap(User::getId, User::getName));
    System.out.println(collect);
    // id作为key,对象作为value
    Map<String, User> userMap =
        Stream.of(user, user1, user2).collect(Collectors.toMap(User::getName, Function.identity()));
    System.out.println(userMap);

    /*
     * Collectors.joining() 拼接,有三个重载方法,底层实现是StringBuilder,
     * 通过append方法拼接到一起,并且可以自定义分隔符
     * (这个感觉还是很有用的,很多时候需要把一个list转成一个String,指定分隔符就可以实现了,非常方便)、前缀、后缀
     */
    String names =
        Stream.of(user, user1, user2).map(User::getName).collect(Collectors.joining(","));
    String names1 =
        Stream.of(user, user1, user2).map(User::getName).collect(Collectors.joining(",", "[", "]"));

    // Collectors.counting() 统计元素个数和Stream.count() 作用都是一样,使用场景还是有区别的
    Long aLong = Stream.of(user, user1, user2).collect(Collectors.counting());
    System.out.println(aLong);
    long count = Stream.of(user, user1, user2).count();
    System.out.println(count);

    // Collectors.minBy()、Collectors.maxBy()和Stream.min()、Stream.max() 作用也是一样的
    Stream.of(user, user1, user2)
        .map(User::getId)
        .collect(Collectors.maxBy(Long::compareTo))
        .ifPresent(System.out::println);

    // Collectors.summarizingLong()、Collectors.summarizingLong()、Collectors.summarizingDouble()
    // 这三个分别用于int、long、double类型数据一个求总操作,返回的是一个SummaryStatistics(求总),包含了数量统计count、求和sum、最小值min、平均值average、最大值max
    // 虽然IntStream、DoubleStream、LongStream 都可以是求和sum但是也仅仅只是求和,没有summing结果丰富。
    // 如果要一次性统计、求平均值什么的,summing还是非常方便的。
    IntSummaryStatistics summaryStatistics =
        Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
            .collect(Collectors.summarizingInt(Integer::valueOf));
    System.out.println(summaryStatistics.getMax());
    System.out.println(summaryStatistics.getMin());
    System.out.println(summaryStatistics.getSum());
    System.out.println(summaryStatistics.getAverage());
    // 求总和、最大、最小、平均值
    Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
        .mapToInt(Integer::valueOf)
        .min()
        .ifPresent(System.out::println);
    Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
        .mapToInt(Integer::valueOf)
        .max()
        .ifPresent(System.out::println);
    System.out.println(Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).mapToInt(Integer::valueOf).sum());
    System.out.println(
        Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).mapToInt(Integer::valueOf).average());

    // Collectors.averagingInt()、Collectors.averagingDouble()、Collectors.averagingLong()
    // 求平均值,适用于高级场景
    System.out.println(
        Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
            .collect(Collectors.averagingInt(Integer::valueOf)));

    // Collectors.reducing() 好像也和Stream.reduce()差不多,也都是规约操作。其实Collectors.counting() 就是用reducing()实现的

    /*
     * *前后处理
     */
    // Collectors.groupingBy()和Collectors.groupingByConcurrent():
    // 这两者区别也仅是单线程和多线程的使用场景,为什么要groupingBy归类为前后处理呢?
    // groupingBy 是在数据收集前分组的,再将分好组的数据传递给下游的收集器
    Map<Long, List<User>> collect1 =
        Stream.of(user, user1, user2, user3)
            .collect(
                Collectors.groupingBy(
                    User::getParentId,
                    Collectors.mapping(Function.identity(), Collectors.toList())));
    System.out.println(collect1);

    // Collectors.mapping() 可以自定义要收集的字段。  以下2种方式是等价的
    List<Long> longs =
        Stream.of(user, user1, user2, user3)
            .collect(Collectors.mapping(User::getId, Collectors.toList()));
    longs.forEach(System.out::println);
    List<Long> longs1 =
        Stream.of(user, user1, user2, user3).map(User::getId).collect(Collectors.toList());
    longs1.forEach(System.out::println);

    // Collectors.collectingAndThen()收集后操作,如果你要在收集数据后再做一些操作,那么这个就非常有用了。
    ListIterator<User> collect2 =
        Stream.of(user, user1, user2, user3)
            .collect(Collectors.collectingAndThen(Collectors.toList(), List::listIterator));
    collect2.forEachRemaining(System.out::println);

  }

  /** * 终止操作符,不包括collect */
  public static void finishOperator() {
    // count操作符:统计数据流中的元素个数,返回的是long 类型
    long count = Stream.of("apple", "banana", "orange", "waltermaleon", "grape", "grape").count();
    System.out.println(count);

    // findFirst操作符: 获取流中的第一个元素
    Optional<String> first =
        Stream.of("apple", "banana", "orange", "waltermaleon", "grape", "grape").findFirst();
    first.ifPresent(System.out::println);

    // findAny操作符: 获取流中任意一个元素  在parallel(并行流)的情况下每次获取结果可能不一样
    Optional<String> any =
        Stream.of("apple", "banana", "orange", "waltermaleon", "grape", "grape")
            .parallel()
            .findAny();
    any.ifPresent(System.out::println);

    // noneMatch操作符:若流中的元素都与指定的元素不匹配则返回true
    System.out.println(Stream.of("aac", "bb", "cc", "aa").noneMatch(e -> e.length() == 3));
    System.out.println(Stream.of("aa", "bb", "cc", "aa").noneMatch("aa"::equals));

    // allMatch anyMatch 和noneMatch操作符同理,allMatch是全匹配上为true,anyMatch是一个匹配上则为true
    System.out.println(Stream.of("aa", "bb", "cca", "aa").allMatch(e -> e.length() == 2));
    System.out.println(Stream.of("aa", "bb", "cc", "aa").anyMatch("aa"::equals));

    // min操作符:最小的一个,传入比较器,也可能没有(如果数据流为空)
    System.out.println(Stream.of(0, 9, 8, 4, 5, 6, -1).min((a, b) -> a - b).get());

    // max操作符:最大的一个,传入比较器,也可能没有(如果数据流为空)
    System.out.println(Stream.of(0, 9, 8, 4, 5, 6, -1).max((a, b) -> a - b).get());

    // reduce操作符:规约操作,所有的元素归约成一个,比如对所有元素求和,乘啊等
    System.out.println(Stream.of(0, 9, 8, 4, 5, 6, -1).reduce(Integer::sum).get());
    System.out.println(Stream.of(0, 9, 8, 4, 5, 6, -1).reduce((a, b) -> a * b).get());

    // toArray操作符:转成数组,可以提供自定义数组生成器
    Object[] objects = Stream.of(0, 2, 6, 5, 4, 9, 8, -1).toArray();
    System.out.println(Arrays.toString(objects));
    // 转换成指定类型数组
    Integer[] integers = Stream.of(0, 2, 6, 5, 4, 9, 8, -1).toArray(Integer[]::new);
    System.out.println(Arrays.toString(integers));
    // 转换成指定类型数组
    Long[] strings = Stream.of(0L, 2L, 6L, 5L, 4L, 9L, 8L, -1L).toArray(Long[]::new);
    System.out.println(Arrays.toString(strings));
  }

  /** *中间操作符 */
  public static void intermediateOperator() {

    List<String> list = Arrays.asList("apple", "banana", "orange", "waltermaleon", "grape");
    // map操作符: 将T类型转换成R类型的
    list.stream().map(String::length).forEach(System.out::println);

    // mapToInt操作符: 将T类型转换成Int类型 (mapToLong、mapToDouble与mapToInt 类似)
    list.stream().mapToInt(String::length).forEach(System.out::println);

    // flatmap操作符: 将元素拍平拍扁 ,将拍扁的元素重新组成Stream,并将这些Stream 串行合并成一条Stream
    Stream.of("a-b-c-d", "e-f-i-g-h")
        .flatMap(i -> Stream.of(i.split("-")))
        .forEach(System.out::println);

    // limit操作符:限制元素的个数,只需传入 long 类型 表示限制的最大数
    Stream.of(1, 2, 3, 4, 5, 6).limit(3).forEach(System.out::println);

    // distinct filter 比较常用不做介绍

    // peek操作符: 挑选 ,将元素挑选出来做处理,
    User user = new User(1L, 1L, "老大");
    User user1 = new User(2L, 1L, "老二");
    User user2 = new User(3L, 1L, "老三");
    Stream.of(user, user1, user2)
        .peek(i -> i.setName(i.getName() + i.getId()))
        .forEach(System.out::println);

    // skip操作符:跳过指定个数的元素
    Stream.of(1, 2, 3, 4, 5, 6).skip(3).forEach(System.out::println);

    // stored:排序,可以自定义比较器,默认从小到大排序
    Stream.of(2, 1, 3, 6, 4, 9, 6, 8, 0).sorted().forEach(System.out::println);
  }
}


class User {

  private Long id;

  private Long parentId;

  private String name;


  public User(Long id, Long parentId, String name) {
    this.id = id;
    this.parentId = parentId;
    this.name = name;
  }

  public Long getId() {
    return id;
  }

  public void setId(Long id) {
    this.id = id;
  }

  public Long getParentId() {
    return parentId;
  }

  public void setParentId(Long parentId) {
    this.parentId = parentId;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  @Override
  public String toString() {
    final StringBuffer sb = new StringBuffer("User{");
    sb.append("id=").append(id);
    sb.append(", parentId=").append(parentId);
    sb.append(", name='").append(name).append('\'');
    sb.append('}');
    return sb.toString();
  }
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值