软件构造——stream的应用

本文深入讲解Java Stream API的原理和应用,包括Stream的概念、操作类型(Intermediate和Terminal)、功能演示及常见操作如构造流、流转换、数据筛选、转换、计算、排序等,帮助读者掌握Stream API的高效数据处理能力。

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

尽管在软件构造实验中,stream仅用于短平快地优化IO,但是作为对集合 (Collection) 对象功能的聚合操作和大批量数据操作的增强,stream还是很值得我们深入学习的。

所谓Stream

不是集合元素,不是数据结构并不保存数据
是有关算法计算的,更像一个高级版本的Iterator,直接进行操作,而且是优化地进行操作

流的操作类型分为两种:
Intermediate:一个流可以后面跟随零个或多个 intermediate 操作。主要是打开流,做出某种程度的数据映射/过滤,然后返回一个新的流,交给下一个操作使用。这类操作都是惰性化的(lazy),就是说,仅仅调用到这类方法,并没有真正开始流的遍历。(例如map(mapToInt,flatMap等), filter, distinct, sorted, peek, limit, skip, parallel, sequential, unordered)

Terminal:一个流只能有一个 terminal 操作,当这个操作执行后,流就被使用“光”了,无法再被操作。所以这必定是流的最后一个操作。Terminal 操作的执行,才会真正开始流的遍历,并且会生成一个结果,或者一个 side effect。(例如:forEach, forEachOrdered, toArray, reduce, collect, min, max, count, anyMatch, allMatch, noneMatch, findFirst, findAny, iterator)

还有一种操作被称为short-circuiting
对于一个 intermediate 操作,如果它接受的是一个无限大的 Stream,但返回一个有限的新 Stream。
对于一个 terminal 操作,如果它接受的是一个无限大的 Stream,但能在有限的时间计算出结果。(例如:anyMatch, allMatch, noneMatch, findFirst, findAny, limit)

 

示例:

int sum = widgets.stream()
.filter(w -> w.getColor() == RED)//根据条件getColor() == RED筛选
 .mapToInt(w -> w.getWeight())//转换getWeight()为int
 .sum();//求和

stream() 获取当前小物件的 source,filter 和 mapToInt 为 intermediate 操作,进行数据筛选和转换,最后一个 sum() 为 terminal 操作,对符合条件的全部小物件作重量求和。

 

运用Stream操作分三步:创建Stream流流中间操作终止流操作

注意: 
1. Stream本省不会存储元素; 
2. Stream不会改变原来源对象,相反,会返回一个持有结果的新Stream; 
3. Stream操作是延迟执行的,这意味着需要数据流通道的计算结果时才执行

 

功能演示

  1. 构造流
    // 1. Individual values 单独值
    Stream stream = Stream.of("a1", "b1", "c1");
    
    // 2. Arrays 数组
    String[] strArray = new String[] {"a2", "b2", "c2"};
    stream = Stream.of(strArray);
    stream = Arrays.stream(strArray);
           
    // 3. Collections 集合
    List<String> list = Arrays.asList(strArray);
    stream = list.stream();
    
  2.  数值流的构造
    IntStream.of(new int[] {1, 2, 3});// 123
    IntStream.range(1, 3);// [1,3) 12
    IntStream.rangeClosed(1, 3);// [1,3] 123
  3. 流转换为其他数据结构 (一个Stream只可以使用一次,否则会报错)
    Stream stream = Stream.of("a1", "b1", "c1");
    
    // 1. Array
    String[] strArray1 = (String[]) stream.toArray(String[]::new);
    
    // 2.Collection list
    stream = Stream.of("a1", "b1", "c1");// stream has already been operated upon or closed
    List<String> list1 = (List<String>) stream.collect(Collectors.toList());
    
    // 3.Collection list
    stream = Stream.of("a1", "b1", "c1");// stream has already been operated upon or closed
    List<String> list2 = (List<String>)stream.collect(Collectors.toCollection(ArrayList::new));
    
    // 4.Collection set
    stream = Stream.of("a1", "b1", "c1");// stream has already been operated upon or closed
    Set<String> set = (Set<String>) stream.collect(Collectors.toSet());
    
    // 5.Collection stack
    stream = Stream.of("a1", "b1", "c1");// stream has already been operated upon or close        Stack<String> stack = (Stack<String>)stream.collect(Collectors.toCollection(Stack::new));
    
    // 6. String
    stream = Stream.of("a1", "b1", "c1");// stream has already been operated upon or closed
    String str = stream.collect(Collectors.joining()).toString();
  4. 转换大写
    Stream<String> stream = Stream.of("hello", "world", "java8", "stream");
    //方法1
    List<String> wordList = stream.map(String::toUpperCase).collect(Collectors.toList());
    //方法2 
    wordList = stream.map(s -> { return s.toUpperCase(); }).collect(Collectors.toList());
    //方法3
    wordList = stream.map(s -> s.toUpperCase()).collect(Collectors.toList());
    
  5. 计算(平方数)
    //map 生产的是个1:1的映射,每个输入元素,都按照规则转换成另一个元素
    Stream<Integer> stream = Arrays.asList(1, 2, 3, 4).stream();
    
    List<Integer> squareList = stream.map(n -> n * n).collect(Collectors.toList());
  6.  一对多 
    //flatMap把input stream中的层级结构扁平化,就是将底层元素抽出来放到一起
    //最终output的Stream里面已经没有List了,都是直接的数字
    Stream<List<Integer>> inputStream = Stream.of(Arrays.asList(1), Arrays.asList(2, 3), Arrays.asList(4, 5, 6));
    Stream<Integer> outputStream = inputStream.flatMap(childList -> childList.stream());
  7.  留下偶数
    Integer[] sixNums = {1, 2, 3, 4, 5, 6};
    Integer[] evens = Stream.of(sixNums).filter(n -> n % 2 == 0).toArray(Integer[]::new);
  8. 把单词挑出来 
    //首先把每行的单词用flatMap整理到新的Stream
    // 1. Java 8 Read File + Stream
    try (Stream<String> stream = Files.lines(path)) {
      List<String> output = stream.flatMap(line -> Stream.of(line.split(" ")))
        .filter(word -> word.length() > 0).collect(Collectors.toList());
    } catch (IOException e) {
      e.printStackTrace();
    }
    
    //然后保留长度不为0的,就是文章中的全部单词了 
    // 2. BufferedReader + Stream
    try (BufferedReader br = Files.newBufferedReader(path)) {
      List<String> output = br.lines().flatMap(line -> Stream.of(line.split(" ")))
        .filter(word -> word.length() > 0).collect(Collectors.toList());
    } catch (IOException e) {
      e.printStackTrace();
    }
    
  9. 排序
     List<String> userList = users.stream()
        .limit(2)
        .sorted((p1, p2) -> p1.getName().compareTo(p2.getName()))
        .map(User::getName) // name_1,name_0,name_0,name_1,
        .collect(Collectors.toList());

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值