01 流创建
1 流支持
Java 8
通过在接口中添加被 default
(默认)修饰的方法,进而将流式(stream
)方法平滑地嵌入到现有类中。流操作的类型有三种:创建流,修改流元素(中间操作,Intermediate Operations
),消费流元素(终端操作,Terminal Operations
)。
2 流创建
(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
3 其他流创建方法
3.1 随机数流
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());}
}
3.2 repeat()
实用小功能 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!
3.3 Stream.generate()
Stream.generate()
的用法,它可以把任意 Supplier<T>
用于生成 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();@Overridepublic 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
3.4 Stream.iterate()
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;@Overridepublic 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);}
}
3.5 流的建造者模式
在建造者模式(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);}}
3.6 Arrays.stream()
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