Collection.stream()入门

Collection.stream()是 Java 8 引入的核心 API,它提供了一种声明式​(Declarative)的方式来处理集合数据,结合 Lambda 表达式和函数式接口,可以极大简化集合操作。

​1. stream()基础用法​

​​(1) 创建 Stream​

ini 复制代码
List<String> list = Arrays.asList("a", "b", "c", "d");

// 1. 顺序流(单线程)
Stream<String> stream = list.stream();

// 2. 并行流(多线程)
Stream<String> parallelStream = list.parallelStream();

​​(2) 常用操作​

​操作类型​ ​方法​ ​说明​
​中间操作​ filter() 过滤元素
map() 转换元素
sorted() 排序
distinct() 去重
limit()/ skip() 截取 / 跳过
​终止操作​ forEach() 遍历
collect() 收集结果
reduce() 归约
count() 计数
anyMatch()/ allMatch()/ noneMatch() 条件匹配

​2. 实战案例​

​​(1) 过滤(filter)​​

ini 复制代码
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");

// 过滤长度 > 3 的名字
List<String> filteredNames = names.stream()
    .filter(name -> name.length() > 3)
    .collect(Collectors.toList());

System.out.println(filteredNames); // [Alice, Charlie, David]

​​(2) 映射(map)​​

ini 复制代码
List<Integer> numbers = Arrays.asList(1, 2, 3, 4);

// 每个数字平方
List<Integer> squares = numbers.stream()
    .map(n -> n * n)
    .collect(Collectors.toList());

System.out.println(squares); // [1, 4, 9, 16]

​​(3) 排序(sorted)​​

ini 复制代码
List<String> names = Arrays.asList("Bob", "Alice", "David", "Charlie");

// 按字母顺序排序
List<String> sortedNames = names.stream()
    .sorted()
    .collect(Collectors.toList());

System.out.println(sortedNames); // [Alice, Bob, Charlie, David]

​​(4) 去重(distinct)​​

ini 复制代码
List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 3, 3);

// 去重
List<Integer> distinctNumbers = numbers.stream()
    .distinct()
    .collect(Collectors.toList());

System.out.println(distinctNumbers); // [1, 2, 3]

​​(5) 统计(count, sum, average)​​

scss 复制代码
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

// 计算总和
int sum = numbers.stream()
    .mapToInt(Integer::intValue)
    .sum();

// 计算平均值
double avg = numbers.stream()
    .mapToInt(Integer::intValue)
    .average()
    .orElse(0.0);

System.out.println("Sum: " + sum); // Sum: 15
System.out.println("Avg: " + avg); // Avg: 3.0

​​(6) 分组(groupingBy)​​

ini 复制代码
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");

// 按首字母分组
Map<Character, List<String>> groupedNames = names.stream()
    .collect(Collectors.groupingBy(name -> name.charAt(0)));

System.out.println(groupedNames);
// {A=[Alice], B=[Bob], C=[Charlie], D=[David]}

​​(7) 归约(reduce)​​

ini 复制代码
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

// 计算乘积
int product = numbers.stream()
    .reduce(1, (a, b) -> a * b);

System.out.println(product); // 120

​3. 高级用法​

​​(1) flatMap(扁平化流)​​

scss 复制代码
List<List<Integer>> nestedList = Arrays.asList(
    Arrays.asList(1, 2),
    Arrays.asList(3, 4),
    Arrays.asList(5, 6)
);

// 扁平化为单层 List
List<Integer> flatList = nestedList.stream()
    .flatMap(List::stream)
    .collect(Collectors.toList());

System.out.println(flatList); // [1, 2, 3, 4, 5, 6]

​​(2) peek(调试流)​​

rust 复制代码
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");

// 打印中间结果
List<String> result = names.stream()
    .peek(System.out::println) // 调试
    .filter(name -> name.length() > 3)
    .collect(Collectors.toList());

// 输出:
// Alice
// Bob
// Charlie
System.out.println(result); // [Alice, Charlie]

​**​(3) findFirst/ findAny**​

ini 复制代码
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");

// 查找第一个匹配的元素
Optional<String> firstMatch = names.stream()
    .filter(name -> name.startsWith("A"))
    .findFirst();

System.out.println(firstMatch.orElse("Not found")); // Alice

​​(4) Collectors.joining(字符串拼接)​​

ini 复制代码
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");

// 拼接字符串
String joined = names.stream()
    .collect(Collectors.joining(", "));

System.out.println(joined); // Alice, Bob, Charlie

​4. 并行流(parallelStream)​​

​​(1) 基本使用​

ini 复制代码
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

// 并行计算平方和
int sum = numbers.parallelStream()
    .mapToInt(n -> n * n)
    .sum();

System.out.println(sum); // 385

​​(2) 适用场景​

  • 大数据量(> 10,000 条数据)
  • CPU 密集型计算(如数学运算)
  • 无状态操作 (如 map、filter)

​​(3) 注意事项​

  • 线程安全问题(避免修改共享数据)
  • 顺序问题 (forEach不保证顺序)
  • 性能测试(小数据量可能更慢)

​5. 性能优化​

​​(1) 避免多次 stream() ​

❌ ​错误写法​(多次创建流):

ini 复制代码
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

// 错误:多次 stream()
long count = numbers.stream().filter(n -> n > 2).count();
int sum = numbers.stream().mapToInt(n -> n).sum();

✅ ​正确写法​(复用流):

ini 复制代码
IntStream intStream = numbers.stream().mapToInt(n -> n);
long count = intStream.filter(n -> n > 2).count();
int sum = intStream.sum(); // 错误!流只能消费一次

​解决方案 ​(使用 Supplier):

ini 复制代码
Supplier<Stream<Integer>> streamSupplier = () -> numbers.stream();

long count = streamSupplier.get().filter(n -> n > 2).count();
int sum = streamSupplier.get().mapToInt(n -> n).sum();

​​(2) 使用 primitive streams(IntStream, LongStream, DoubleStream)​​

ini 复制代码
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

// 避免自动拆箱
int sum = numbers.stream()
    .mapToInt(Integer::intValue) // IntStream
    .sum();

​6. 总结​

​场景​ ​推荐操作​
​过滤数据​ filter()
​转换数据​ map()/ flatMap()
​排序​ sorted()
​去重​ distinct()
​统计​ count()/ sum()/ average()
​分组​ Collectors.groupingBy()
​归约​ reduce()
​并行计算​ parallelStream()

​最佳实践​:

  1. 优先使用 stream() 替代传统 for循环。
  2. 避免多次创建流,尽量复用。
  3. 大数据量考虑 parallelStream,但需测试性能。
  4. **使用 primitive streams** 提升性能。
相关推荐
聪明的笨猪猪33 分钟前
实际工程问题:AI生成Redis分布式锁的原子性缺陷导致库存超卖
java·经验分享·面试·ai编程
软件技术NINI1 小时前
基于SpringBoot和Vue的新能源汽车销售推荐系统
java·vue.js·spring boot·后端·汽车·毕业设计·毕设
Flynn Liang2 小时前
LangChain4j 生产级工程骨架:12 个模块 + Docker 一键启动
java·spring boot·langchain·rag·langchain4j
噢,我明白了3 小时前
JAVA中的一些基础应用知识点
java·开发语言
SL_staff3 小时前
私有化低代码不是妥协,而是企业级数字化的自主可控主航道
java
装不满的克莱因瓶4 小时前
【SpringAI Alibaba】ReactAgent结构化输出OutputType与OutputSchema实战
java·人工智能·ai·springai·springaialibaba
秋天的怀念_David4 小时前
算法一千零一夜 · 第二十八夜 注册
java·程序人生·算法
Java码农也是农4 小时前
Spring 事务详解:@Transactional 如何生效、何时回滚、传播行为怎么选
java·spring boot·spring·事务
学长毕设5 小时前
基于SpringBoot的游乐园管理系统-附源码
java·spring boot·后端
SimonKing5 小时前
震惊:怎么回事,opencode一轮对话耗尽免费额度
java·后端·程序员