设计网络网站,微信小程序开发教程视频,京东网站的建设与发展现状分析,网站结构seo在 Java 8 中添加了 Stream API#xff0c;以简化顺序或并行执行批量操作的任务。 该 API 提供了两个关键的抽象#xff1a;流(Stream)#xff0c;表示有限或无限的数据元素序列#xff0c;以及流管道 (stream pipeline)#xff0c;表示对这些元素的多级计算。 Stream 中的…在 Java 8 中添加了 Stream API以简化顺序或并行执行批量操作的任务。 该 API 提供了两个关键的抽象流(Stream)表示有限或无限的数据元素序列以及流管道 (stream pipeline)表示对这些元素的多级计算。 Stream 中的元素可以来自任何地方。 常见的源包括集合数组文件正则表达式模式匹配器伪随机数生成器和其他流。流中的数据元素可以是对象引用或基本类型。 支持三种基本类型intlong 和 double。
流管道由源流source stream的零或多个中间操作和一个终结操作组成。每个中间操作都以某种方式转换流例如将每个元素映射到该元素的函数或过滤掉所有不满足某些条件的元素。中间操作都将一个流转换为另一个流其元素类型可能与输入流相同或不同。终结操作对流执行最后一次中间操作产生的最终计算例如将其元素存储到集合中、返回某个元素或打印其所有元素。
管道延迟lazily计算求值计算直到终结操作被调用后才开始而为了完成终结操作而不需要的数据元素永远不会被计算出来。 这种延迟计算求值的方式使得可以使用无限流。 请注意没有终结操作的流管道是静默无操作的所以不要忘记包含一个。 Stream API 流式的fluent:它设计允许所有组成管道的调用被链接到一个表达式中。事实上多个管道可以链接在一起形成一个表达式。 默认情况下流管道按顺序 (sequentially) 运行。 使管道并行执行就像在管道中的任何流上调用并行方法一样简单但很少这样做第 48 个条目。 Stream API 具有足够的通用性实际上任何计算都可以使用 Stream 执行但仅仅因为可以并不意味着应该这样做。如果使用得当流可以使程序更短更清晰如果使用不当它们会使程序难以阅读和维护。对于何时使用流没有硬性的规则但是有一些启发。 考虑以下程序该程序从字典文件中读取单词并打印其大小符合用户指定的最小值的所有变位词anagram组。如果两个单词由长度相通不同顺序的相同字母组成则它们是变位词。程序从用户指定的字典文件中读取每个单词并将单词放入 map 对象中。map 对象的键是按照字母排序的单词因此『staple』的键是『aelpst』『petals』的键也是『aelpst』这两个单词就是同位词所有的同位词共享相同的依字母顺序排列的形式或称之为alphagram。map 对象的值是包含共享字母顺序形式的所有单词的列表。 处理完字典文件后每个列表都是一个完整的同位词组。然后程序遍历 map 对象的 values() 的视图并打印每个大小符合阈值的列表
// Prints all large anagram groups in a dictionary iteratively
public class Anagrams {public static void main(String[] args) throws IOException {File dictionary new File(args[0]);int minGroupSize Integer.parseInt(args[1]);MapString, SetString groups new HashMap();try (Scanner s new Scanner(dictionary)) {while (s.hasNext()) {String word s.next();groups.computeIfAbsent(alphabetize(word), (unused) - new TreeSet()).add(word);}}for (SetString group : groups.values())if (group.size() minGroupSize)System.out.println(group.size() : group);}private static String alphabetize(String s) {char[] a s.toCharArray();Arrays.sort(a);return new String(a);}
} 现在考虑以下程序它解决了同样的问题但大量过度使用了流。 请注意整个程序打开字典文件的代码除外包含在单个表达式中。 在单独的表达式中打开字典文件的唯一原因是允许使用 try-with-resources 语句该语句确保关闭字典文件
// Overuse of streams - dont do this!
public class Anagrams {public static void main(String[] args) throws IOException {Path dictionary Paths.get(args[0]);int minGroupSize Integer.parseInt(args[1]);try (StreamString words Files.lines(dictionary)) {words.collect(groupingBy(word - word.chars().sorted().collect(StringBuilder::new,(sb, c) - sb.append((char) c),StringBuilder::append).toString())).values().stream().filter(group - group.size() minGroupSize).map(group - group.size() : group).forEach(System.out::println);}}
} 如果你发现这段代码难以阅读不要担心你不是一个人。它更短但是可读性也更差尤其是对于那些不擅长使用流的程序员来说。过度使用流使程序难于阅读和维护。 幸运的是有一个折中的办法。下面的程序解决了同样的问题使用流而不过度使用它们。其结果是一个比原来更短更清晰的程序
// Tasteful use of streams enhances clarity and conciseness
public class Anagrams {public static void main(String[] args) throws IOException {Path dictionary Paths.get(args[0]);int minGroupSize Integer.parseInt(args[1]);try (StreamString words Files.lines(dictionary)) {words.collect(groupingBy(word - alphabetize(word))).values().stream().filter(group - group.size() minGroupSize).forEach(g - System.out.println(g.size() : g));}}// alphabetize method is the same as in original version
} 请注意仔细选择 lambda 参数名称。 上面程序中参数 g 应该真正命名为 group但是生成的代码行对于本书来说太宽了。 在没有显式类型的情况下仔细命名 lambda 参数对于流管道的可读性至关重要。
另请注意单词字母化是在单独的 alphabetize 方法中完成的。 这通过提供操作名称并将实现细节保留在主程序之外来增强可读性。 使用辅助方法对于流管道中的可读性比在迭代代码中更为重要因为管道缺少显式类型信息和命名临时变量。 流可以很容易地做一些事情
· 统一转换元素序列 · 过滤元素序列 · 使用单个操作组合元素序列 (例如添加、连接或计算最小值) · 将元素序列累积到一个集合中可能通过一些公共属性将它们分组 · 在元素序列中搜索满足某些条件的元素 总之有些任务最好使用流来完成有些任务最好使用迭代来完成。将这两种方法结合起来可以最好地完成许多任务。对于选择使用哪种方法进行任务没有硬性规定但是有一些有用的启发式方法。在许多情况下使用哪种方法将是清楚的在某些情况下则不会很清楚。如果不确定一个任务是通过流还是迭代更好地完成那么尝试这两种方法看看哪一种效果更好。