教材
《Java核心技术·卷II 高级特性(原书第11版)》
《Java语言程序设计(第3版)》
目录
2.3 静态方法 Stream.generate() 和 Stream.iterate()
一、Stream流介绍
Stream流用来以“做什么而非怎么做”的方式处理集合。
Stream流并不存储集合的元素。
Stream流的操作不会修改数据源。
Stream流的操作只在需要结果时执行(惰性执行)。
二、创建Stream流
2.1 静态方法 Stream.of()
// 直接传入元素创建
Stream<Integer> stream = Stream.of(0, 1, 2, 3);
// 用数组创建
String[] names = {"Oliver", "John", "Steve"};
Stream<String> stream = Stream.of(names);
2.2 类和接口的 stream() 方法
String[] names = {"Oliver", "John", "Steve"};
Stream<String> stream = Arrays.stream(names);
List<String> nameList = new ArrayList<>(Arrays.asList(names));
String<String> stream = nameList.stream();
2.3 静态方法 Stream.generate() 和 Stream.iterate()
用于创建无限流
Stream.generate() 接受一个无参数的函数(Supplier<T>接口的对象)
Stream<String> echos = Stream.generate(() -> "Oliver");
Stream<Double> randoms = Stream.generate(Math::random);
Stream.iterate() 接受一个带有初始值(“种子”)的函数(UnaryOperator<T>接口的对象)
Stream<BigInteger> integers = Stream.iterate(
BigInteger.ZERO, // 初始值(“种子”)
integer -> integer.add(BigInteger.ONE) // 对 integer(初始为“种子”) 加1
);
可以添加谓词逻辑描述无限流应该如何结束,以此获得一个有限流
BigInteger limit = new BigInteger("10000000");
Stream<BigInteger> integers = Stream.iterate(
BigInteger.ZERO, // 初始值(“种子”)
integer -> integer.comparaTo(limit) < 0, // 满足谓词逻辑再进行下一步
integer -> integer.add(BigInteger.ONE) // 对 integer(初始为“种子”) 加1
);
三、操作Stream流
3.1 过滤流 filter() 方法
Stream<T> filter(Predicate<? super T> predicate)
筛选单词列表 words 中单词长度大于12的单词
List<String> words = ...;
Stream<String> longWords = words.stream().filter(word -> word.length() > 12);
3.2 转换流 map() 和 flatMap() 方法
按照某种方式转换流中的值
<R> Stream<R> map(Function<? super T, ? extends Stream<? extends R>> mapper)
List<String> words = ...;
// 将所有单词首字母小写
Stream<String> lowerCaseWords = words.stream().map(String::toLowerCase);
// 提取所有单词首字母
Stream<String> firstLetters = words.stream.map(s -> s.substring(0, 1));
将mapper应用于当前流中所有元素,将产生的(流)结果连接在一起
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)
// 得到每个单词的所有字母
List<String> words = ...;
Stream<Stream<string>> result = words.stream().map(word -> codePoints(word)); // codePoint("Oliver")的返回值是Stream流 ["O", "l", "i", "v", "e", "r"]
Stream<String> flatResult = words.stream().flatMap(word -> codePoints(word));
3.3 限制流
Stream<T> limit(long maxSize)
产生一个流 其中包含当前流中前 maxSize 个元素
Stream<Double> randoms = Stream.generate(Math::random).limit(100)
Stream<T> skip(long n)
产生一个流 其中包含当前流中除前 n 个元素以外的所有元素
List<Integer> numbers = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
Stream<Integer> skippedNumbers = numbers.stream().skip(5);
Stream<T> takeWhile(Predicate<? super T> predicate)
产生一个流 逐个获取当前流中的元素 直到条件不成立 不再获取当前流中后面的元素
List<String> lines = List.of("Header", "Data1", "Data2", "EOF", "Footer");
Stream<String> data = lines.stream().takeWhile(line -> !line.equals("EOF"));
Stream<T> dropWhile(Predicate<? super T> predicate)
产生一个流 逐个跳过当前流中的元素 直到条件不成立 获取当前流中剩下没有被跳过的元素
List<String> lines = List.of("# Comment", "# Metadata", "Data1", "Data2", "Data3");
Stream<String> data = lines.stream().dropWhile(line -> line.startsWith("#")) // 跳过所有以 # 开头的行
3.4 合并流 静态方法 concat()
static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)
将两个流连接起来
Stream<String> combined = Stream.concat(
codePoints("Hello"),
codePoints("Oliver"));
// ["H", "e", "l", "l", "o", "O", "l", "i", "v", "e", "r"]
3.5 剔除重复元素 distinct() 方法
Stream<T> distinct()
Stream<String> uniqueWords = Stream.of("Hello", "Hello", "Hello", "Oliver").distinct();
// ["Hello", "Oliver]
3.6 排序元素 sorted() 方法
Stream<T> sorted()
Stream<T> sorted(Comparator<? super T> comparator)
// 按长度逆序排序字符串
List<String> words = ...;
Stream<String> longestFirst = words.stream().sorted(Comparator.comparing(String::length).reversed)
3.7 遍历操作元素 forEach() 方法
void forEach(Consumer<? super T> action)
List<String> words = ...;
words.stream().forEach(System.out::println);
四、归纳Stream流
归纳(reduction)是一种终结操作。
4.1 简单归纳
long count()
返回流中元素的数量
Optional<T> max(Comparator<? super T> comparator)
返回流中最大的元素
Optional<T> min(Comparator<? super T> comparator)
返回流中最小的元素
Optional<T> findFirst()
返回流中第一个元素
Optional<T> findAny()
返回流中任意一个元素
boolean anyMatch(Predicate<? super T> predicate)
如果流中有任意一个元素满足条件则返回true
boolean allMatch(Predicate<? super T> predicate)
如果流中所有元素都满足条件则返回true
boolean noneMatch(Predicate<? super T> predicate)
如果流中没有一个元素满足条件则返回true
4.2 Optional 类型
Optional<T>对象是一种包装器对象 要么包装了类型T的对象 要么没有包装任何对象
4.2.1 获取类型T的对象
T orElse(T other)
返回包装的对象 在为空时返回other
String result = optionalString.orElse("");
T orElseGet(Supplier<? extends T> other)
返回包装的对象 在为空时返回other产生的结果
String result = optionalString.orElseGet(
() -> System.getProperty("myapp.default")
);
<X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier)
返回包装的对象 在为空时抛出调用exceptionSupplier的结果
String result = optionalString.orElseThrow(IllegalStateException::new);
4.2.2 操作类型T的对象
void ifPresent(Consumer<? super T> action)
如果不为空 对包装的对象执行操作action
optionalValue.ifPresent(results:add);
void ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction)
如果不为空 对包装的对象执行操作action,否则调用emptyAction
optionalValue.ifPresentOrElse(
v -> System.out.println("Found" + v),
() -> logger.warning("No match")
);
<U> Optional<U> map(Function<? super T, ? extends U> mapper)
产生一个Optional对象,如果当前Optional对象不为空,则产生的Optional对象的值通过使用mapper转换当前Optional对象的值得到。否则,产生一个空Optional对象。
Optional<String> transformed = optionalString.map(String::toLowerCase);
Optional<T> filter(Predicate<? supper T> predicate)
产生一个Optional对象,如果当前Optional对象的值满足给定条件,产生的Optional对象的值即为该值。否则,产生一个空Optional对象。
Optional<String> transformed = optionalString.filter(s -> s.length() > 8);
Optional<T> or(Supplier<? extends Optional<? extends T>> supplier)
如果当前Optional对象不为空 则产生当前的Optional对象。否则由supplier产生一个Optional对象。
Optional<String> result = optionalString.or(() -> alternatives.stream().findFirst());
4.2.3 创建Optional对象
static <T> Optional<T> of(T value)
static <T> Optional<T> ofNullable(T value)
static <T> Optional<T> empty()
五、收集Stream流
Object[] toArray()
产生一个对象数组。
<A> A[] toArray(IntFunction<A[]> generator)
将引用A[]::new传递给构造器时,返回一个A类型的数组 。
String[] result = stream.toArray(String[]::new);
<R, A> R collect(Collector<? super T, A, R> collector)
使用给定的收集器来收集当前流中的元素。
将流的元素收集到一个列表中
List<String> result = stream.collect(Collectors.toList());
将流的元素收集到一个集合中
Set<String> result = stream.collect(Collectors.toSet());
将流的元素收集到指定列表或指定集合中
List<String> result = stream.collect(Collectors.toCollection(LinkedList::new));
Set<String> result = stream.collect(Collectors.toCollection(HashSet::new));
六、基本类型流
IntStream 存储 short char byte boolean
LongStream 存储 long
DoubleStream 存储 float double
编程练习
import java.util.stream.Stream;
public class SevenRandomNumber {
public static void main(String[] args) {
Stream<Integer> numbers = Stream.generate(() -> (int) (Math.random() * (999 - 100) + 100))
.limit(1000)
.filter(number -> number % 7 == 0 || number.toString().contains("7"))
.peek(System.out::println);
System.out.println("The quantity of numbers : " + numbers.count());
}
}