mirror of
https://github.com/LingCoder/OnJava8.git
synced 2026-08-23 22:43:28 +08:00
更新 Ranges of int 和 generate() 小节
更新 Ranges of int 和 generate() 小节
This commit is contained in:
@@ -256,9 +256,192 @@ it shop sir the much cheese by conclusion district is
|
||||
在 **main()** 中,我们看到了 **Stream.generate()** 的预览版本,它可以把任意 **Supplier\<T\>** 用于生成 **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\<T\>**。这里是第二个示例:
|
||||
|
||||
```java
|
||||
// streams/Generator.java
|
||||
import java.util.*;
|
||||
import java.util.function.*;
|
||||
import java.util.stream.*;
|
||||
|
||||
public class Generator implements Supplier<String> {
|
||||
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\<Bubble\>** 是接口兼容的,我们可以将其方法引用直接传递给 **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()
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user