Java 8
通过在接口中添加被 default
(默认)修饰的方法,进而将流式(stream
)方法平滑地嵌入到现有类中。流操作的类型有三种:创建流,修改流元素(中间操作,Intermediate Operations
),消费流元素(终端操作,Terminal Operations
)。
(1)Stream.of()
public static<T> Stream<T> of(T t) {
return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false);
}
package com.hcong.streams;
import java.util.stream.Stream;
/**
* @Classname StreamOf
* @Date 2023/4/14 9:43
* @Created by HCong
*/
public class StreamOf {
public static void main(String[] args) {
Stream.of("It's ", "a ", "wonderful ", "day ", "for ", "pie!").forEach(System.out::print);
System.out.println();
Stream.of(3.14159, 2.718, 1.618).forEach(System.out::println);
}
}
It's a wonderful day for pie!
3.14159
2.718
1.618
(2)调用每个集合的 stream()
方法
package com.hcong.streams;
import java.util.*;
/**
* @Classname CollectionToStream
* @Date 2023/4/14 9:45
* @Created by HCong
*/
public class CollectionToStream {
public static void main(String[] args) {
Set<String> w = new HashSet<>(Arrays.asList("It's a wonderful day for pie!".split(" ")));
w.stream()
.map(x -> x + " ")
.forEach(System.out::print);
System.out.println();
Map<String, Double> m = new HashMap<>();
m.put("pi", 3.14159);
m.put("e", 2.718);
m.put("phi", 1.618);
m.entrySet().stream()
.map(e -> e.getKey() + ": " + e.getValue())
.forEach(System.out::println);
}
}
a pie! It's for wonderful day
phi: 1.618
e: 2.718
pi: 3.14159
package com.hcong.streams;
import java.util.Random;
import java.util.stream.Stream;
/**
* @Classname RandomGenerators
* @Date 2023/4/14 9:54
* @Created by HCong
*/
public class RandomGenerators {
public static <T> void show(Stream<T> stream) {
stream
.limit(4)
.forEach(System.out::println);
System.out.println("=============================");
}
public static void main(String[] args) {
Random rand = new Random(47);
show(rand.ints().boxed());
show(rand.longs().boxed());
show(rand.doubles().boxed());
// 控制上限和下限:
show(rand.ints(10, 20).boxed());
show(rand.longs(50, 100).boxed());
show(rand.doubles(20, 30).boxed());
// 控制流大小:
show(rand.ints(2).boxed());
show(rand.longs(2).boxed());
show(rand.doubles(2).boxed());
// 控制流的大小和界限
show(rand.ints(3, 3, 9).boxed());
show(rand.longs(3, 12, 22).boxed());
show(rand.doubles(3, 11.5, 12.3).boxed());
}
}
实用小功能 repeat()
可以用来替换简单的 for
循环。
package com.hcong.utils;
import java.util.stream.IntStream;
/**
* @Classname Repeat
* @Date 2023/4/14 13:53
* @Created by HCong
*/
public class Repeat {
public static void repeat(int n, Runnable r) {
IntStream.range(0, n).forEach(i -> r.run());
}
}
package com.hcong.streams;
import com.hcong.utils.Repeat;
/**
* @Classname Looping
* @Date 2023/4/14 13:55
* @Created by HCong
*/
public class Looping {
static void hi() {
System.out.println("Hi!");
}
public static void main(String[] args) {
Repeat.repeat(3, () -> System.out.println("Hello"));
Repeat.repeat(3, Looping::hi);
}
}
Hello
Hello
Hello
Hi!
Hi!
Hi!
Stream.generate()
的用法,它可以把任意 Supplier
用于生成 T
类型的流。
public static<T> Stream<T> generate(Supplier<? extends T> s) {
Objects.requireNonNull(s);
return StreamSupport.stream(
new StreamSpliterators.InfiniteSupplyingSpliterator.OfRef<>(Long.MAX_VALUE, s), false);
}
package com.hcong.streams;
import java.util.Random;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @Classname Generator
* @Date 2023/4/14 14:01
* @Created by HCong
*/
public class Generator implements Supplier<String> {
Random rand = new Random(47);
char[] letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
@Override
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);
}
}
YNZBRNYGCFOWZNTCQRGSEGZMMJMROE
Stream.iterate()
产生的流的第一个元素是种子(iterate
方法的第一个参数),然后将种子传递给方法(iterate
方法的第二个参数)。方法运行的结果被添加到流(作为流的下一个元素),并被存储起来,作为下次调用 iterate()
方法时的第一个参数,以此类推。
public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f) {
Objects.requireNonNull(f);
Spliterator<T> spliterator = new Spliterators.AbstractSpliterator<>(Long.MAX_VALUE,
Spliterator.ORDERED | Spliterator.IMMUTABLE) {
T prev;
boolean started;
@Override
public boolean tryAdvance(Consumer<? super T> action) {
Objects.requireNonNull(action);
T t;
if (started)
t = f.apply(prev);
else {
t = seed;
started = true;
}
action.accept(prev = t);
return true;
}
};
return StreamSupport.stream(spliterator, false);
}
package com.hcong.streams;
import java.util.stream.Stream;
/**
* @Classname Fibonacci
* @Date 2023/4/14 14:10
* @Created by HCong
*/
public class Fibonacci {
int x = 1;
Stream<Integer> numbers() {
return Stream.iterate(0, i -> {
// iterate() 只能记忆结果,因此我们需要利用一个变量 x 追踪另外一个元素。
int result = i + x;
x = i;
return result;
});
}
public static void main(String[] args) {
new Fibonacci().numbers()
.skip(20)
.limit(10)
.forEach(System.out::println);
}
}
在建造者模式(Builder design pattern
)中,首先创建一个 builder
对象,然后将创建流所需的多个信息传递给它,最后 builder
对象执行”创建流的操作。
package com.hcong.streams;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Stream;
/**
* @Classname FileToWordsBuilder
* @Date 2023/4/14 14:17
* @Created by HCong
*/
public class FileToWordsBuilder {
Stream.Builder<String> builder = Stream.builder();
public FileToWordsBuilder(String filePath) throws IOException {
Files.lines(Paths.get(filePath))
.skip(1)
.forEach(line -> {
for (String w : line.split("[ .?,]+"))
builder.add(w);
});
}
// 只要你不调用 stream() 方法,就可以继续向 builder 对象中添加单词。
Stream<String> stream() {
return builder.build();
}
public static void main(String[] args) throws IOException {
new FileToWordsBuilder("E:\\Projects\\IdeaProjects\\OnJava\\src\\com\\hcong\\streams\\Cheese.dat")
.stream()
.limit(7)
.map(w -> w + " ")
.forEach(System.out::print);
}
}
Arrays
类中含有一个名为 stream()
的静态方法用于把数组转换成为流。
public static <T> Stream<T> stream(T[] array) {
return stream(array, 0, array.length);
}
public static <T> Stream<T> stream(T[] array, int startInclusive, int endExclusive) {
return StreamSupport.stream(spliterator(array, startInclusive, endExclusive), false);
}
package com.hcong.streams;
import com.hcong.utils.Operations;
import java.util.Arrays;
/**
* @Classname Machine2
* @Date 2023/4/14 14:21
* @Created by HCong
*/
public class Machine2 {
public static void main(String[] args) {
Arrays.stream(new Operations[]{
() -> Operations.show("Bing"),
() -> Operations.show("Crack"),
() -> Operations.show("Twist"),
() -> Operations.show("Pop")
}).forEach(Operations::execute);
}
}
Bing
Crack
Twist
Pop