Java中的Stream

定义

  • 是Java8新增的接口,也可以认为是一个高级版本的Iterator
  • 用于操作集合、数组等数据源的API,主要进行数据的转换、筛选、聚合等操作
  • 可以避免显示地使用迭代器或循环来操作集合,提高代码可读性和简洁性

特点

  • 无存储性:是基于数据源的对象,它本身不存储元素,而是通过管道将数据源元素传递给操作
  • 函数式编程:任何修改都不会修改背后的数据源,例如filter操作不会删除被过滤的元素,而是会产生一个不包含被过滤元素的新的Stream
  • 延迟执行:由0个或多个中间操作和一个结束操作两部分组成。只有执行结束操作,定义的中间操作才会依次执行
  • 可消费型:只能被“消费”依次,一旦遍历就会失效,类似于迭代器,想重新遍历重新生成

操作符 

操作分类名称含义示例
中间操作符无状态指元素的处理不受之前元素的影响unordered() filter() map() mapToInt() flatMap() flatMapToInt() peek()
有状态指该操作只有拿到所有的元素之后才能继续下去dintinct() sorted() limit() skip()
终端操作符非短路操作指必须处理所有元素才能得到最终结果foreach() foreachOrdered()  toArray() reduce() collect() max() min() count()
短路操作指遇到某些符合条件的元素就可以得到最终结果,如A或B,只要A为true,则无需判断B的结果anyMatch() allMatch() noneMatch() findFirst() findAny()

注意事项

  • 一旦创建一个Stream对象并执行终端操作,该Stream就不能再被重用,需重新创建
  • Stream是惰性求值,中间操作只会在终端操作触发后才会执行
  • 若使用并行流,要确保线程安全,避免引发并发问题
  • 使用基于IO的流,使用完需要关闭
  • Stream的操作性能可能会受到数据量的影响,可以考虑使用并行流
  • 要注意空值null的处理,避免空指针异常。可以用filter、map的那个进行过滤和映射
  • 有状态的操作,例如sorted/distinct,可能需要缓存所有元素,避免内存溢出
  • 推荐不可变对象和不可变集合来处理Stream,避免并发问题

使用

创建Stream

  • 集合的stream()方法创建流
  • Arrays.stream()方法从数组中创建一个流
  • Files.lines()方法从文件中创建一个流
  • parallelStream()方法获取并行流
  • 静态方法of()创建一个包含指定元素的流
  • 静态方法iterate()用于生成一个由初始值和给定的生成器函数组成的无限流
  • 静态方法generate()用于创建一个无限流,‌该流通过提供的Supplier生成元素
  • 使用BufferedReader.lines()方法,将每行内容转换成流
  • 使用Pattern.splitAsStream()方法,将字符串分割成流
public class streamTest {
    public static void main(String[] args) {
        //集合中获取一个顺序流
        List<String> list = new ArrayList<>();
        Stream<String> stream = list.stream();
        //获取一个并行流
        Stream<String> parallelStream = list.parallelStream();

        //数组中创建一个流
        Integer[] nums = new Integer[10];
        Stream<Integer> integerStream = Arrays.stream(nums);

        //文件中创建一个流
        try (Stream<String> lines = Files.lines(Paths.get("data.txt"), Charset.defaultCharset())) {
            //处理文件中的每一行数据
            lines.forEach(System.out::println);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //静态方法of()创建一个包含指定元素的流
        Stream<Integer> stream1 = Stream.of(1, 2, 3, 4, 5, 6, 7, 8);
        //静态方法iterate()用于生成一个由初始值和给定的生成器函数组成的无限流
        //使用limit防止无限生成
        Stream<Integer> stream2 = Stream.iterate(0, (x) -> x + 2).limit(6);
        //静态方法generate()用于创建一个无限流,‌该流通过提供的Supplier生成元素
        //使用limit防止无限生成
        Stream<Double> stream3 = Stream.generate(Math::random).limit(4);

        //使用BufferedReader.lines()方法,将每行内容转换成流
        try {
            BufferedReader bufferedReader = new BufferedReader(new FileReader("D:\\data.txt"));
            Stream<String> lineStream = bufferedReader.lines();
            lineStream.forEach(System.out::println);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        //使用Pattern.splitAsStream()方法,将字符串分割成流
        Pattern pattern = Pattern.compile(",");
        Stream<String> stringStream = pattern.splitAsStream("a,s,d,f,g,h");
        stringStream.forEach(System.out::println);
    }
}

中间操作(Intermediate)

  • 对流的一系列处理步骤,返回一个新的流,允许链式调用
  • 通常对于数据进行过滤,映射,排除等操作
  • filter(Predicate<T> predicate):根据条件过滤元素
  • map<Function<T,R> mapper>:将元素映射为新的值,有返回值
  • sorted():对元素进行排序
  • dinctinct():去重
  • limit(long maxSize):限制元素的数量
  • skip(long n):跳过元素前n个元素
  • flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)通常用于集合扁平化
  • peek(Consumer<T> action):对流中元素执行指定操作,无返回值
public class IntermediateStream {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 5, 6, 6);
        //根据指定条件筛选元素
        //输出为[2,4,6]
        List<Integer> list1 = list.stream().filter(n -> n % 2 == 0).collect(Collectors.toList());
        System.out.println(list1);
        //将元素映射为新值或另一种类型
        List<Integer> list2 = list.stream().map(n -> n * 2).collect(Collectors.toList());
        System.out.println(list2);
        List<String> list3 = list.stream().map(n -> "Number" + n).collect(Collectors.toList());
        System.out.println(list3);
        //排序
        List<Integer> list4 = list.stream().sorted().collect(Collectors.toList());
        System.out.println(list4);
        //去重
        List<Integer> list5 = list.stream().distinct().collect(Collectors.toList());
        System.out.println(list5);
        //限制元素数量
        List<Integer> list6 = list.stream().limit(3).collect(Collectors.toList());
        System.out.println(list6);
        //跳过前n个元素
        List<Integer> list7 = list.stream().skip(3).collect(Collectors.toList());
        System.out.println(list7);
        //FlatMap()
        List<List<Integer>> list8=Arrays.asList(
                Arrays.asList(1,2),
                Arrays.asList(3,4,5),
                Arrays.asList(6,7,8,9,10)
        );
        List<Integer> flat=list8.stream().flatMap(Collection::stream).collect(Collectors.toList());
        System.out.println(flat);
        //peek()
        List<Integer> list9=list.stream().peek(n->System.out.println("Process element :"+n)).collect(Collectors.toList());

    }
}

 运行结果

 

终端操作(Terminal)

  • 流的最后一个步骤,它会触发对流的计算并产生一个最终结果
  • forEach(Consumer<T> action):对流中的每个元素执行操作
  • collect(Collector<T,A,R> collector):将流中的元素收集到一个容器中
  • toArray():将流中的元素收集到数组中
  • reduce():对流中的元素进行归约处理操作,返回一个值
  • count():返回流中元素的数量
  • min(comparator):返回流中的最小元素
  • max(comparator):返回流中的最大元素
  • allMatch(predicate):检查流中的所有元素是否都满足条件
  • anyMatch(predicate):检查流中是否存在满足条件的元素
  • noneMatch(predicate):检查流中是否没有元素满足条件
  • findFirst():返回流中的第一个元素
  • findAny():返回流中的任意一个元素
public class TerminalStream {
    public static void main(String[] args) {
        //forEach
        List<String> list = Arrays.asList("Tom", "SuSan", "Lucy");
        list.stream().forEach(n -> System.out.println("Hello " + n));
        //toArray
        List<Integer> list1 = Arrays.asList(1, 2, 3, 4);
        Integer[] numArray = list1.stream().toArray(Integer[]::new);
        //reduce(identity,accumulator)
        List<Integer> list2 = Arrays.asList(1, 2, 3, 4, 5, 6);
        int sum = list2.stream().reduce(0, (a, b) -> a + b);
        System.out.println(sum);
        //collect
        List<String> list3 = list.stream().collect(Collectors.toList());
        Set<String> set = list.stream().collect(Collectors.toSet());
        Map<String, Integer> map = list.stream().collect(Collectors.toMap(n -> n, String::length));
        System.out.println(list3);
        System.out.println(set);
        System.out.println(map);
        //min(comparator) max(comparator)
        Optional<Integer> min = list1.stream().min(Integer::compareTo);
        Optional<Integer> max = list1.stream().max(Integer::compareTo);
        //输出1
        System.out.println(min.orElse(0));
        //输出6
        System.out.println(max.orElse(0));
        //allMatch(predicate):检查流中的所有元素是否都满足条件
        //anyMatch(predicate):检查流中是否存在满足条件的元素
        //noneMatch(predicate):检查流中是否没有元素满足条件
        boolean all1 = list1.stream().allMatch(n -> n > 3);
        boolean any1 = list1.stream().anyMatch(n -> n > 3);
        boolean none1 = list1.stream().noneMatch(n -> n > 10);
        System.out.println(all1);
        System.out.println(any1);
        System.out.println(none1);
        //findFirst():返回流中的第一个元素
        //findAny():返回流中的任意一个元素
        Optional<String> first2=list.stream().findFirst();
        Optional<String> any2=list.stream().findAny();
        System.out.println(first2.orElse(null));
        System.out.println(any2.orElse(null));
    }
}

运行结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值