Java Stream流

参考资料: Java入门到飞起

1. 引言

随着Java版本的不断演进,Java 8引入了Stream流,Stream流是一种用于处理集合数据的抽象概念,它允许开发者以声明式的方式处理数据,就像流水线上的工序一样,将各种操作串联起来完成复杂的数据转换和处理任务。而方法引用则进一步简化了Lambda表达式的使用,使得代码更加简洁明了。

本文将深入探讨Java Stream流和方法引用的核心概念、使用场景和最佳实践。我们将从基础概念入手,逐步讲解Stream流的创建方式、中间操作和终结操作。

2. Stream流

2.1 体验Stream流

案例需求

按照以下要求完成集合的创建和遍历:

  1. 创建一个集合,存储多个字符串元素
  2. 把集合中所有以"张"开头的元素存储到一个新的集合
  3. 把"张"开头的集合中的长度为3的元素存储到一个新的集合
  4. 遍历上一步得到的集合
原始方式实现

jdk1.8使用List.of()会报错的,9版本以上是可以用;8版本的话,可以用add一点点加。

public class MyStream1 {
    public static void main(String[] args) {
        // 集合初始化
        ArrayList<String> list1 = new ArrayList<>(List.of("张三丰","张无忌","张翠山","王二麻子","张良","谢广坤"));
        
        // 筛选以"张"开头的元素
        ArrayList<String> list2 = new ArrayList<>();
        for (String s : list1) {
            if(s.startsWith("张")){
                list2.add(s);
            }
        }
        
        // 筛选长度为3的元素
        ArrayList<String> list3 = new ArrayList<>();
        for (String s : list2) {
            if(s.length() == 3){
                list3.add(s);
            }
        }
        
        // 遍历输出
        for (String s : list3) {
            System.out.println(s);
        }      
    }
}
Stream流实现
import java.util.ArrayList;
public class MyStream1 {
    public static void main(String[] args) {
        // 集合初始化
        ArrayList<String> list1 = new ArrayList<>();
        list1.add("张三丰");
        list1.add("张无忌");
        list1.add("张翠山");
        list1.add("王二麻子");
        list1.add("张良");
        list1.add("谢广坤");

        // 使用 Stream API 筛选并输出结果
        list1.stream()
             .filter(s -> s.startsWith("张"))
             .filter(s -> s.length() == 3)
             .forEach(System.out::println);
    }
}
Stream流优势
  • 代码简洁:一行代码完成传统方式多行才能完成的操作
  • 可读性强:方法链直观表达数据处理流程
  • 函数式编程:引入Java的函数式编程范式

2.2 Stream流的常见生成方式

Stream流思想

Stream流可以看作数据的"流水线",数据从源头进入,经过一系列处理,最终被消费。

生成方式
集合类型生成方式示例
Collectionstream()方法list.stream()
Map转换为Set后获取流map.keySet().stream()
数组Arrays.stream()Arrays.stream(arr)
多个数据Stream.of()Stream.of(1,2,3)
代码示例
public class StreamDemo {
    public static void main(String[] args) {
        // Collection生成流
        List<String> list = new ArrayList<>();
        Stream<String> listStream = list.stream();
        
        // Map生成流
        Map<String,Integer> map = new HashMap<>();
        Stream<String> keyStream = map.keySet().stream();
        
        // 数组生成流
        String[] strArray = {"a", "b", "c"};
        Stream<String> arrayStream = Arrays.stream(strArray);
        
        // 多个数据生成流
        Stream<String> ofStream = Stream.of("x", "y", "z");
    }
}

2.3 Stream流中间操作方法

中间操作特点
  • 返回新的Stream对象
  • 可以链式调用多个中间操作
  • 不立即执行,形成流水线
方法说明示例
filter()过滤元素.filter(s -> s.startsWith("张"))
limit()限制数量.limit(3)
skip()跳过元素.skip(2)
concat()合并流Stream.concat(s1, s2)
distinct()去重.distinct()
代码示例
package stream;

import java.util.ArrayList;
import java.util.stream.Stream;

/**
 * 该类演示了如何使用 Stream 流对集合进行过滤、限制和跳过操作。
 */
public class StreamDemo {
    public static void main(String[] args) {
        ArrayList<String> names = new ArrayList<String>();

        names.add("林青霞");
        names.add("张曼玉");
        names.add("王祖贤");
        names.add("柳岩");
        names.add("张敏");
        names.add("张无忌");
        
        // 过滤以"张"开头的名字
        System.out.println("1.过滤姓张的人--------");
        names.stream()
             .filter(s -> s.startsWith("张"))
             .forEach(System.out::println);
        System.out.println("--------");
        // 限制前3个元素
        System.out.println("2.限制前三个元素--------");
        names.stream()
             .limit(3)
             .forEach(System.out::println);
        System.out.println("--------");     
        // 跳过前2个元素
        System.out.println("3.跳过第二个元素--------");
        names.stream()
             .skip(2)
             .forEach(System.out::println);
        System.out.println("--------");
        // 合并两个流并去重
        System.out.println("4. 合并2,3并去重--------");
        Stream<String> s1 = names.stream().limit(3);
        Stream<String> s2 = names.stream().skip(2);
        Stream.concat(s1, s2).distinct().forEach(System.out::println);
    }
}

结果输出:

1.过滤姓张的人--------
张曼玉
张敏
张无忌
--------
2.限制前三个元素--------
林青霞
张曼玉
王祖贤
--------
3.跳过第二个元素--------
王祖贤
柳岩
张敏
张无忌
--------
4. 合并23并去重--------
林青霞
张曼玉
王祖贤
柳岩
张敏
张无忌
PS E:\Trae\Traeproject>

2.4 Stream流终结操作方法

终结操作特点
  • 执行后会关闭流,不能继续使用
  • 通常用于获取结果或执行副作用操作
方法说明示例
forEach()遍历元素.forEach(System.out::println)
count()计数.count()
代码示例
public class StreamDemo {
    public static void main(String[] args) {
        List<String> names = List.of("张三丰", "张无忌", "张翠山");
        
        // 遍历元素
        names.stream()
             .forEach(System.out::println);
             
        // 计数
        long count = names.stream()
                          .filter(s -> s.startsWith("张"))
                          .count();
        System.out.println("以张开头的人数: " + count);
    }
}

2.5 Stream流的收集操作【应用】

收集操作

将Stream中的元素收集到集合或其他数据结构中

方法说明示例
toList()收集到List.collect(Collectors.toList())
toSet()收集到Set.collect(Collectors.toSet())
toMap()收集到Map.collect(Collectors.toMap(...))
代码示例
public class StreamDemo {
    public static void main(String[] args) {
        List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        
        // 收集到List
        List<Integer> evenNumbers = numbers.stream()
                                           .filter(n -> n % 2 == 0)
                                           .collect(Collectors.toList());
        
        // 收集到Set
        Set<Integer> oddNumbers = numbers.stream()
                                         .filter(n -> n % 2 != 0)
                                         .collect(Collectors.toSet());
        
        // 收集到Map
        List<String> personList = List.of("张三,25", "李四,30", "王五,28");
        Map<String, Integer> personMap = personList.stream()
                                                   .filter(s -> {
                                                       String[] parts = s.split(",");
                                                       return Integer.parseInt(parts[1]) >= 25;
                                                   })
                                                   .collect(Collectors.toMap(
                                                       s -> s.split(",")[0],
                                                       s -> Integer.parseInt(s.split(",")[1])
                                                   ));
    }
}

2.6 Stream流综合练习

案例需求

处理演员数据:

  1. 男演员:名字为3个字的前三人
  2. 女演员:姓林的,并且不要第一个
  3. 合并结果创建Actor对象
代码实现
// Actor类
public class Actor {
    private String name;
    
    public Actor(String name) {
        this.name = name;
    }
    
    // getter/setter...
    
    @Override
    public String toString() {
        return "Actor{name='" + name + "'}";
    }
}

// 测试类
public class StreamTest {
    public static void main(String[] args) {
        ArrayList<String> manList = List.of("周润发", "成龙", "刘德华", "吴京", "周星驰", "李连杰");
        ArrayList<String> womanList = List.of("林心如", "张曼玉", "林青霞", "柳岩", "林志玲", "王祖贤");
        
        // 处理男演员
        Stream<String> manStream = manList.stream()
                                          .filter(s -> s.length() == 3)
                                          .limit(3);
        
        // 处理女演员
        Stream<String> womanStream = womanList.stream()
                                              .filter(s -> s.startsWith("林"))
                                              .skip(1);
        
        // 合并并创建Actor对象
        Stream.concat(manStream, womanStream)
              .map(Actor::new)  // 方法引用创建Actor
              .forEach(System.out::println);  // 方法引用打印
    }
}

结果输出:

Actor{name='周润发'}
Actor{name='刘德华'}
Actor{name='周星驰'}
Actor{name='林青霞'}
Actor{name='林志玲'}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

码银

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

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

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

打赏作者

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

抵扣说明:

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

余额充值