Skip to content

Commit b51d7df

Browse files
authored
第十四章 iterate() 、Stream Builders、Arrays翻译
第十四章 iterate() 、Stream Builders、Arrays翻译
1 parent e453b45 commit b51d7df

File tree

1 file changed

+161
-0
lines changed

1 file changed

+161
-0
lines changed

Diff for: docs/book/14-Streams.md

+161
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,167 @@ Bubble(4)
443443
444444
### iterate()
445445
446+
**Stream.iterate()** 以种子(第一个参数)开头,并将其传给方法(第二个参数)。方法的结果将添加到流,并存储作为第一个参数用于下次调用 **iterate()**,依次类推。我们可以使用 **iterate()** 用于生成一个 Fibonacci 序列(你在上一章中遇到):
447+
448+
```java
449+
// streams/Fibonacci.java
450+
import java.util.stream.*;
451+
public class Fibonacci {
452+
int x = 1;
453+
454+
Stream<Integer> numbers() {
455+
return Stream.iterate(0, i -> {
456+
int result = x + i;
457+
x = i;
458+
return result;
459+
});
460+
}
461+
462+
public static void main(String[] args) {
463+
new Fibonacci().numbers()
464+
.skip(20) // Don't use the first 20
465+
.limit(10) // Then take 10 of them
466+
.forEach(System.out::println);
467+
}
468+
}
469+
```
470+
471+
输出为:
472+
473+
```java
474+
6765
475+
10946
476+
17711
477+
28657
478+
46368
479+
75025
480+
121393
481+
196418
482+
317811
483+
514229
484+
```
485+
486+
Fibonacci 序列将序列中最后两个元素进行求和以产生下一个元素。**iterate()** 只能记忆结果,因此我们需要使用一个变量 **x** 来用于追踪另外一个元素。
487+
488+
在 **main()** 中,我们使用了一个你之前没有见过的 **skip() ** 操作。它只是根据它的参数丢弃指定数量的流元素。在这里,我们丢弃了前 20 个元素。
489+
490+
### Stream Builders
491+
492+
在建造者设计模式中,首先创建一个 builder 对象,传递给它多个构造器信息,最后执行“构造”。**Stream** 库提供了这样的 **Builder**。在这里,我们重新审视读取文件并将其转换成为单词流的过程:
493+
494+
```java
495+
// streams/FileToWordsBuilder.java
496+
import java.io.*;
497+
import java.nio.file.*;
498+
import java.util.stream.*;
499+
500+
public class FileToWordsBuilder {
501+
Stream.Builder<String> builder = Stream.builder();
502+
503+
public FileToWordsBuilder(String filePath) throws Exception {
504+
Files.lines(Paths.get(filePath))
505+
.skip(1) // Skip the comment line at the beginning
506+
.forEach(line -> {
507+
for (String w : line.split("[ .?,]+"))
508+
builder.add(w);
509+
});
510+
}
511+
512+
Stream<String> stream() {
513+
return builder.build();
514+
}
515+
516+
public static void main(String[] args) throws Exception {
517+
new FileToWordsBuilder("Cheese.dat")
518+
.stream()
519+
.limit(7)
520+
.map(w -> w + " ")
521+
.forEach(System.out::print);
522+
}
523+
}
524+
```
525+
526+
输出为:
527+
528+
```java
529+
Not much of a cheese shop really
530+
```
531+
532+
注意,构造器会添加文件中的所有单词(除了第一行,它是包含文件路径信息的注释),但是其并没有调用 **build()** 方法。这意味着,只要你不调用 **stream()** 方法,就可以继续向 **builder** 对象中添加单词。
533+
534+
在此类的更完整的版本中,你可以添加一个标志位用于查看 **build()** 方法是否被调用,并且可能的话增加一个可以添加更多单词的方法。在 **Stream.Builder** 调用 **build()** 方法后继续尝试添加单词会产生一个异常。
535+
536+
### Arrays
537+
538+
**Arrays** 类中含有一个名为 **stream()** 的静态方法用于把数组转换成为流。我们可以重写 **interfaces/Machine.java** 中的 **main()** 方法用于创建一个流,并将 **execute()** 应用于每一个元素:
539+
540+
```java
541+
// streams/Machine2.java
542+
import java.util.*;
543+
import onjava.Operations;
544+
public class Machine2 {
545+
public static void main(String[] args) {
546+
Arrays.stream(new Operations[] {
547+
() -> Operations.show("Bing"),
548+
() -> Operations.show("Crack"),
549+
() -> Operations.show("Twist"),
550+
() -> Operations.show("Pop")
551+
}).forEach(Operations::execute);
552+
}
553+
}
554+
```
555+
556+
输出为:
557+
558+
```java
559+
Bing
560+
Crack
561+
Twist
562+
Pop
563+
```
564+
565+
**new Operations[]** 表达式动态创建了 **Operations** 对象的数组。
566+
567+
**stream()** 方法同样可以产生 **IntStream**,**LongStream** 和 **DoubleStream**。
568+
569+
```java
570+
// streams/ArrayStreams.java
571+
import java.util.*;
572+
import java.util.stream.*;
573+
574+
public class ArrayStreams {
575+
public static void main(String[] args) {
576+
Arrays.stream(new double[] { 3.14159, 2.718, 1.618 })
577+
.forEach(n -> System.out.format("%f ", n));
578+
System.out.println();
579+
580+
Arrays.stream(new int[] { 1, 3, 5 })
581+
.forEach(n -> System.out.format("%d ", n));
582+
System.out.println();
583+
584+
Arrays.stream(new long[] { 11, 22, 44, 66 })
585+
.forEach(n -> System.out.format("%d ", n));
586+
System.out.println();
587+
588+
// Select a subrange:
589+
Arrays.stream(new int[] { 1, 3, 5, 7, 15, 28, 37 }, 3, 6)
590+
.forEach(n -> System.out.format("%d ", n));
591+
}
592+
}
593+
```
594+
595+
输出为:
596+
597+
```java
598+
3.141590 2.718000 1.618000
599+
1 3 5
600+
11 22 44 66
601+
7 15 28
602+
```
603+
604+
最后一次 **stream()** 的调用有两个额外的参数。第一个参数告诉 **stream()** 从哪里开始在数组中选择元素,第二个参数用于告知在哪里停止。每种不同类型的 **stream()** 方法都有这个版本。
605+
606+
### 正则表达式(Regular Expressions)
446607
447608
448609

0 commit comments

Comments
 (0)