Java 的每个新版本都变得越来越丰富。虽然大部分丰富性都存在于早期版本中,但该语言在方法论和实现方面都在不断改进。Java 中的集合也不例外。 核心集合框架出现在 J2SE 1.2 中,并继续发展,所经历的变化令人愉快而不是令人失望。随着 JDK 5 的发布,集合变得更加方便、更快、更容易使用。这导致程序员开始更集中地利用它们。已经开发出一些与它们一起工作的模式,这无疑是有效的。但在 JDK 8 中,集合再次变得更好,并且得益于线程,它们变得更好。显然,由于集合可以以流的形式表示,因此使用它们的方法也会发生变化。因此,我想展示熟悉且易于理解的集合解决方案如何变得更加简单。
- 示例 1. 再简单不过了
- 示例2.在列表中查找偶数值并将其显示在控制台中
- 示例 3. 让我们计算一下列表中有多少个单词长度为 5 个字符
- 示例 4. 打印唯一单词
- 示例 5. 长单词
- 示例 6. 带数字的单词
- 示例 7. 选择数字
示例 1. 再简单不过了
当然,我们从最简单的开始,遍历集合的所有元素,并显示所有元素。// создадим и заполним список
List<Integer> list = new ArrayList<>();
Collections.addAll(list, 1, 5, 6, 11, 3, 15, 7, 8);
// а теперь
// быстрый for по всем elementм, только для коллекций
for (Integer i:list){
System.out.println(i);
}
//но мы уже живем в JDK 8
//а значит нужно так
list.stream().forEach(System.out::println);
正如您所注意到的,作为 Java 新手,我认为有一种新语法要简单得多。那么,新语法中可见的内容是:
берем_список(list).превращаем_в_поток(stream).перебираем_все_элементы(forEach)(тут_интуитивно_понятно)
System.out::println
— 指向将字符串输出到控制台的静态方法的链接 您可以使用稍有不同、不太清晰的条目,而不是指向静态方法的链接:
list.stream().forEach(i -> System.out.println(i));
此条目使用 lambda 表达式。是的,要学习如何使用流,您需要学习 lambda 表达式 - 它们非常棒。此外,我不会展示如何仅使用流来处理集合,因为您在课程中已经熟悉了传统方法。
示例2.在列表中查找偶数值并将其显示在控制台中
list.stream().filter(i -> i%2==0).forEach(System.out::println);
整个问题一口气解决了。我希望你喜欢在一条线上工作。使用该方法,filter
我们过滤了流并将剩下的内容输出到控制台。过滤器是一个非常强大的东西,可以在最意想不到的情况下提供帮助。让我们发挥创造力并改变问题的条件。例如,我们需要计算列表中有多少个偶数:
long count = list.stream().filter(i -> i%2==0).count();
又排成一行。不知何故,一切似乎都很简单。在过滤器中,我们使用了 lambda 表达式,从而仅将偶数放入新流中,然后应用于新流count
,计算新流中有多少个元素。
示例 3. 让我们计算一下列表中有多少个单词长度为 5 个字符
我们已经玩过整数了,现在让我们玩一下单词吧。List<String> list = new ArrayList<>();
Collections.addAll(list, "разые", "слова", "интересные", "And", "Not", "Very");
System.out.println(list.stream().filter(w -> w.length() == 5).count());
我们再次使用过滤器。在过滤器中,使用 lambda 表达式显示一个新流,然后,可以理解的是,count
我计算了新流中有多少元素。
示例 4. 打印唯一单词
当我们从文件中将许多不同的单词读入集合中时,这是一个熟悉的任务,而现在我们只需要唯一的单词。List<String> list = new ArrayList<>();
Collections.addAll(list, "Vasya", "Таня", "Olya", "Vasya", "Olya", "Сергей");
list.stream().distinct().forEach(System.out::println);
主要操作是使用在流上完成的distinct
。接下来,我建议使用线程查看课程中的一些任务
示例 5. 长单词
Java核心第9级,第11讲有一个有趣的问题,就是你需要在File2中写出以逗号分隔的单词,其长度严格大于6。无论你围栏的是哪种花园,我提出以下解决方案:-
从源文件中,我们将所有单词读入列表中。
-
然后我们执行以下行
Optional<String> rezult = list.stream() .filter(w->w.length()>6) .reduce((w1,w2)->w1+", "+w2);
-
result.get()
写入文件。
示例 6. 带数字的单词
在 File2 中写入所有包含数字的单词,例如 a1 或 abc3d,并用空格分隔。这也是我们习题册上的一个条件,正如你猜到的,解决办法很简单。Optional<String> rezult = list.stream()
.filter(w->w.matches(".*?\\d+.*?"))
.reduce((w1,w2)->w1+" "+w2);
我们使用正则表达式过滤流,然后使用reduce 和lambda 表达式。与之前的任务有很多共同点。
示例 7. 选择数字
整个任务听起来是这样的:- 从控制台读取2个文件名。
- 将第一个文件中的所有数字输出到第二个文件中。
- 数字之间用空格分隔。
- 关闭溪流。
Optional<String> rezult = list.stream().filter(w->w.matches("\\d+"))
.reduce((w1,w2)->w1+" "+w2);
System.out.println(rezult.get());
使用线程,问题就以非常简单的方式解决了。但是,您瞧,请将此解决方案与之前的两个解决方案进行比较。在文章结束时,我想向你们坦白:伙计们,我在选择示例时作弊了。事实上,我选择了最简单的例子,以便用熟悉的问题向您展示一个不熟悉的主题。当然,线程既可用于简单任务,也可用于更复杂的任务。但正如霍斯特曼在他的书中强调的那样,“数据流的运作原则是‘做什么,而不是如何做’”,这意味着许多以前复杂的任务可以变得更简单。我不了解你,但我喜欢这些流程,我希望我没有阻止你学习它们。让我再解释一件事:
- 我并不是要教读者如何在集合中使用流;我不是一位经验丰富的老师。我想向您展示线程是简单且非常有趣的!一般来说,这是必要的。
- 我对流了解得越多,我看到的问题就越多,它们解决了课本上的所有问题,这意味着流不是白发明的。
- 流不仅易于使用,而且还具有一个重要的优势 - 在处理大量数据时,流通常更加高效。
GO TO FULL VERSION