跳转到内容
主菜单
主菜单
移至侧栏
隐藏
导航
首页
最近更改
随机页面
MediaWiki帮助
代码酷
搜索
搜索
中文(中国大陆)
外观
创建账号
登录
个人工具
创建账号
登录
未登录编辑者的页面
了解详情
贡献
讨论
编辑“︁
Java Stream最佳实践
”︁
页面
讨论
大陆简体
阅读
编辑
编辑源代码
查看历史
工具
工具
移至侧栏
隐藏
操作
阅读
编辑
编辑源代码
查看历史
常规
链入页面
相关更改
特殊页面
页面信息
外观
移至侧栏
隐藏
您的更改会在有权核准的用户核准后向读者展示。
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
= Java Stream最佳实践 = Java Stream API是Java 8引入的一个强大的功能,它允许开发者以声明式的方式处理数据集合。Stream API提供了一种高效且易于理解的方式来处理数据,尤其是对于集合的操作。本文将详细介绍Java Stream的最佳实践,帮助初学者和高级用户更好地利用这一功能。 == 介绍 == Java Stream API是Java 8中引入的一个新特性,它允许开发者以函数式编程的方式处理数据集合。Stream API的核心思想是将数据集合视为一个流(Stream),然后通过一系列的操作(如过滤、映射、排序等)来处理这些数据。Stream API的主要优势在于它的声明式编程风格,使得代码更加简洁、易读,并且可以利用多核架构进行并行处理。 Stream API的主要特点包括: * '''惰性求值''':Stream的操作是惰性的,只有在需要结果时才会执行。 * '''不可变性''':Stream不会修改原始数据源,而是生成一个新的Stream。 * '''并行处理''':Stream可以轻松地并行化,以提高处理速度。 == 基本概念 == === 创建Stream === Stream可以通过多种方式创建,例如从集合、数组或直接生成。 <syntaxhighlight lang="java"> // 从集合创建Stream List<String> list = Arrays.asList("a", "b", "c"); Stream<String> streamFromList = list.stream(); // 从数组创建Stream String[] array = {"a", "b", "c"}; Stream<String> streamFromArray = Arrays.stream(array); // 直接生成Stream Stream<String> generatedStream = Stream.of("a", "b", "c"); </syntaxhighlight> === 中间操作与终端操作 === Stream的操作分为中间操作和终端操作。中间操作返回一个新的Stream,而终端操作返回一个非Stream的结果或产生副作用。 <syntaxhighlight lang="java"> List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David"); // 中间操作:过滤和映射 Stream<String> filteredStream = names.stream() .filter(name -> name.length() > 4) .map(String::toUpperCase); // 终端操作:收集结果 List<String> result = filteredStream.collect(Collectors.toList()); System.out.println(result); // 输出: [ALICE, CHARLIE, DAVID] </syntaxhighlight> == 最佳实践 == === 1. 优先使用方法引用 === 方法引用可以使代码更加简洁和易读。 <syntaxhighlight lang="java"> List<String> names = Arrays.asList("Alice", "Bob", "Charlie"); // 使用Lambda表达式 names.stream().map(name -> name.toUpperCase()).collect(Collectors.toList()); // 使用方法引用 names.stream().map(String::toUpperCase).collect(Collectors.toList()); </syntaxhighlight> === 2. 避免副作用 === Stream操作应该是无副作用的,避免在中间操作中修改外部状态。 <syntaxhighlight lang="java"> // 不推荐:在forEach中修改外部状态 List<String> result = new ArrayList<>(); names.stream().forEach(name -> result.add(name.toUpperCase())); // 推荐:使用collect List<String> result = names.stream() .map(String::toUpperCase) .collect(Collectors.toList()); </syntaxhighlight> === 3. 使用并行Stream谨慎 === 并行Stream可以提高性能,但并非所有情况下都适用。只有在数据量大且操作耗时的情况下才考虑使用并行Stream。 <syntaxhighlight lang="java"> List<String> names = Arrays.asList("Alice", "Bob", "Charlie"); // 顺序Stream List<String> result = names.stream() .map(String::toUpperCase) .collect(Collectors.toList()); // 并行Stream List<String> parallelResult = names.parallelStream() .map(String::toUpperCase) .collect(Collectors.toList()); </syntaxhighlight> === 4. 使用短路操作优化性能 === 短路操作(如`limit`、`findFirst`)可以在满足条件时提前终止Stream的处理,从而提高性能。 <syntaxhighlight lang="java"> List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David"); // 使用limit限制结果数量 List<String> limitedResult = names.stream() .filter(name -> name.length() > 4) .limit(2) .collect(Collectors.toList()); System.out.println(limitedResult); // 输出: [Alice, Charlie] </syntaxhighlight> === 5. 使用Collectors工具类 === `Collectors`类提供了许多有用的方法,如`groupingBy`、`partitioningBy`等,可以简化集合的操作。 <syntaxhighlight lang="java"> List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David"); // 按名字长度分组 Map<Integer, List<String>> groupedByLength = names.stream() .collect(Collectors.groupingBy(String::length)); System.out.println(groupedByLength); // 输出: {3=[Bob], 5=[Alice, David], 7=[Charlie]} </syntaxhighlight> == 实际案例 == === 案例1:统计单词频率 === 给定一个字符串列表,统计每个单词出现的频率。 <syntaxhighlight lang="java"> List<String> words = Arrays.asList("apple", "banana", "apple", "orange", "banana", "apple"); Map<String, Long> frequencyMap = words.stream() .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); System.out.println(frequencyMap); // 输出: {orange=1, banana=2, apple=3} </syntaxhighlight> === 案例2:筛选并排序 === 从一个员工列表中筛选出薪资大于5000的员工,并按薪资降序排序。 <syntaxhighlight lang="java"> class Employee { String name; int salary; Employee(String name, int salary) { this.name = name; this.salary = salary; } // getters and setters } List<Employee> employees = Arrays.asList( new Employee("Alice", 6000), new Employee("Bob", 4500), new Employee("Charlie", 7000) ); List<Employee> filteredAndSorted = employees.stream() .filter(e -> e.salary > 5000) .sorted(Comparator.comparing(Employee::getSalary).reversed()) .collect(Collectors.toList()); filteredAndSorted.forEach(e -> System.out.println(e.name + ": " + e.salary)); // 输出: // Charlie: 7000 // Alice: 6000 </syntaxhighlight> == 性能优化 == === 使用原始类型Stream === 对于基本数据类型(如`int`、`long`、`double`),使用原始类型Stream(如`IntStream`、`LongStream`)可以避免装箱/拆箱的开销。 <syntaxhighlight lang="java"> List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); // 使用IntStream int sum = numbers.stream() .mapToInt(Integer::intValue) .sum(); System.out.println(sum); // 输出: 15 </syntaxhighlight> === 避免重复计算 === 如果需要对同一个Stream进行多次操作,可以考虑将其结果缓存起来。 <syntaxhighlight lang="java"> List<String> names = Arrays.asList("Alice", "Bob", "Charlie"); // 不推荐:重复创建Stream long count = names.stream().count(); List<String> upperCaseNames = names.stream() .map(String::toUpperCase) .collect(Collectors.toList()); // 推荐:缓存Stream Stream<String> stream = names.stream(); count = stream.count(); stream = names.stream(); // 需要重新创建Stream,因为Stream只能使用一次 upperCaseNames = stream.map(String::toUpperCase).collect(Collectors.toList()); </syntaxhighlight> == 总结 == Java Stream API是一个强大的工具,可以极大地简化集合操作。通过遵循上述最佳实践,您可以编写出高效、易读且易于维护的代码。记住: * 优先使用方法引用。 * 避免副作用。 * 谨慎使用并行Stream。 * 利用短路操作优化性能。 * 使用`Collectors`工具类简化操作。 通过实际案例和性能优化技巧,您可以更好地掌握Stream API,并在实际项目中灵活运用。 == 参见 == * [[Java Lambda表达式]] * [[Java集合框架]] * [[函数式编程]] [[Category:编程语言]] [[Category:Java]] [[Category:Java Stream API]]
摘要:
请注意,所有对代码酷的贡献均被视为依照知识共享署名-非商业性使用-相同方式共享发表(详情请见
代码酷:著作权
)。如果您不希望您的文字作品被随意编辑和分发传播,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)