From c5f41a699a2bf287f788579a2003054a9207d460 Mon Sep 17 00:00:00 2001 From: Joe <736777445@qq.com> Date: Tue, 9 Apr 2019 15:52:50 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20Ranges=20of=20int=20?= =?UTF-8?q?=E5=92=8C=20generate()=20=E5=B0=8F=E8=8A=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 更新 Ranges of int 和 generate() 小节 --- docs/book/14-Streams.md | 185 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 184 insertions(+), 1 deletion(-) diff --git a/docs/book/14-Streams.md b/docs/book/14-Streams.md index 5db76eb..d46b2ad 100644 --- a/docs/book/14-Streams.md +++ b/docs/book/14-Streams.md @@ -256,9 +256,192 @@ it shop sir the much cheese by conclusion district is 在 **main()** 中,我们看到了 **Stream.generate()** 的预览版本,它可以把任意 **Supplier\** 用于生成 **T** 类型的流。 - ### int 类型的范围(Ranges of int) +**IntStream** 类提供了 **range()** 方法用于生成整数序列的流。编写循环时,这个方法会更加便利: + +```java +// streams/Ranges.java +import static java.util.stream.IntStream.*; +public class Ranges { + public static void main(String[] args) { + // The traditional way: + int result = 0; + for (int i = 10; i < 20; i++) + result += i; + System.out.println(result); + // for-in with a range: + result = 0; + for (int i : range(10, 20).toArray()) + result += i; + System.out.println(result); + // Use streams: + System.out.println(range(10, 20).sum()); + } +} +``` + +输出为: + +```java +145 +145 +145 +``` + +在 **main()** 方法中的第一种方式是我们传统编写 **for** 循环的方式。在第二种方法,我们使用 **range()** 创建了流并将其转化为数组,然后在 **for-in** 代码块中使用。但是,如果你能够像第三种方法全程使用流是很好的。在每种情况下,我们对范围中的数字进行求和,并且流中可以很方便的使用 **sum()** 操作求和。 + +注意 **IntStream.range()** 相比 **onjava.Range.range()** 拥有更多的限制。这是由于其可选的第三个参数,后者能够生成步长大于 1 的范围,并且可以从大到小来生成。 + +为了替换简单的 **for** 循环,这里是一个 **repeat()** 实用程序: + +```java +// onjava/Repeat.java +package onjava; +import static java.util.stream.IntStream.*; +public class Repeat { + public static void repeat(int n, Runnable action) { + range(0, n).forEach(i -> action.run()); + } +} +``` + +其产生的循环更加清晰: + +```java +// streams/Looping.java +import static onjava.Repeat.*; +public class Looping { + static void hi() { + System.out.println("Hi!"); + } + public static void main(String[] args) { + repeat(3, () -> System.out.println("Looping!")); + repeat(2, Looping::hi); + } +} +``` + +输出为: + +```java +Looping! +Looping! +Looping! +Hi! +Hi! +``` + +在代码中包含并解释 **repeat()** 似乎有些不值得。它似乎是一个相当透明的工具,但它取决于你的团队和公司的运作方式 + +### generate() + +**RandomWords.java** 在 **Stream.generate()** 中使用 **Supplier\**。这里是第二个示例: + +```java +// streams/Generator.java +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +public class Generator implements Supplier { + Random rand = new Random(47); + char[] letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray(); + + public String get() { + return "" + letters[rand.nextInt(letters.length)]; + } + + public static void main(String[] args) { + String word = Stream.generate(new Generator()) + .limit(30) + .collect(Collectors.joining()); + System.out.println(word); + } +} +``` + +输出为: + +```java +YNZBRNYGCFOWZNTCQRGSEGZMMJMROE +``` + +使用 **Random.nextInt()** 方法来挑选字母表中的大写字母。**Random.nextInt()** 的参数代表可以接受的最大的随机数范围,所以使用数组边界是经过深思熟虑的。 + +如果要创建包含相同对象的流,只需要传递一个生成那些对象 **lambda** 到 **generate()** 中: + +```java +// streams/Duplicator.java +import java.util.stream.*; +public class Duplicator { + public static void main(String[] args) { + Stream.generate(() -> "duplicate") + .limit(3) + .forEach(System.out::println); + } +} +``` + +输出为: + +```java +duplicate +duplicate +duplicate +``` + +如下是在这个章节中之前例子使用过的 **Bubble** 类。注意它包含了自己的静态生成器(*static generator*)方法。 + +```java +// streams/Bubble.java +import java.util.function.*; +public class Bubble { + public final int i; + + public Bubble(int n) { + i = n; + } + + @Override + public String toString() { + return "Bubble(" + i + ")"; + } + + private static int count = 0; + public static Bubble bubbler() { + return new Bubble(count++); + } +} +``` + +由于 **bubbler()** 与 **Supplier\** 是接口兼容的,我们可以将其方法引用直接传递给 **Stream.generate()**: + +```java +// streams/Bubbles.java +import java.util.stream.*; +public class Bubbles { + public static void main(String[] args) { + Stream.generate(Bubble::bubbler) + .limit(5) + .forEach(System.out::println); + } +} +``` + +输出为: + +```java +Bubble(0) +Bubble(1) +Bubble(2) +Bubble(3) +Bubble(4) +``` + +这是创建单独工厂类( separate factory class)的另外一种方式。在很多方面它更加整洁,但是这代表着品味和代码组织的问题 - 你总是可以创建一个完全不同的工厂类。 + +### iterate()