在前一篇文章浅析Java中的Steam流中讲述了流式思想和Java中更适用于函数式编程的Stream流,以及Stream流中的一些常用方法,如
forEach()、filter()、map()、count()、limit()、skip()、concat()。本文中将讲述Stream中更多的方法,以及java.util.stream包下更多类型的Stream。
文章目录
1. 创建Stream流
前一篇文章中介绍了最为常用的两个创建Stream流的方法,即:
-
Collection集合的``stream()` 获取集合对应的Stream流
- 使用
Stream.of()创建包含多个数据的Stream流
- 使用
除此之外,Stream中还有更多用于创建流的方法,如:
static <T> Stream<T> empty()用于创建一个空流static <T> Stream<T> generate(Supplier<? extends T> s):创建一个无限流,流中的元素通过反复调用s函数产生static <T> Stream<T> iterate(T seed, UnaryOperator<T> f):创建一个无限流,参数包含seed、在seed上调用f产生的值、在前一个元素上调用f产生的值static <T> Stream<T> iterate(T seed, Predicate<? super T> hasNext, UnaryOperator<T> next):类似于上一个方法,不同之处在于流会在遇到的第一个不满足hasNext条件时终止
import java.math.BigInteger;
import java.util.*;
import java.util.stream.Stream;
public class SomeMethodsAboutGetStream {
public static void main(String[] args) {
// 创建空流
final Stream<Object> empty = Stream.empty();
empty.forEach(k-> System.out.println(k)); //
System.out.println("-------------------");
// 创建无限流
BigInteger limit = new BigInteger("1000000");
Stream.generate(()->"Hello").limit(5).forEach(k -> System.out.println(k));
Stream.iterate(BigInteger.ZERO, n -> n.add(BigInteger.ONE)).limit(5).forEach(System.out::println);
System.out.println("-------------------");
Stream<Object> s15 = Stream.ofNullable(10);
s15.forEach(System.out::println); // 10
System.out.println("-------------------");
}
}
2. 抽取子流和组合流
类如之前的limit()、skip()和cooncat()都属于此类范畴的方法,它们会返回一个包含部分元素的新流。除此之外,相关的方法还有:
default Stream<T> takeWhile(Predicate<? super T> predicate):产生一个流,流中的元素满足传入的谓词条件default Stream<T> dropWhile(Predicate<? super T> predicate):产生一个流,流的元素是当前流中排除不满足谓词条件的元素之外的所有元素
import java.math.BigInteger;
import java.util.*;
import java.util.stream.Stream;
public class SomeMethodsAboutGetStream {
public static void main(String[] args) {
Stream<String> s0 = Stream.of("Forlogen", "Kobe", "James", "Bill", "Forever");
Stream<String> s1 = Stream.of("Forlogen", "Kobe", "James", "Bill");
s0.takeWhile(ss -> ss.startsWith("F")).forEach(System.out::println); // Forlogen
s1.dropWhile(ss -> ss.startsWith("F")).forEach(System.out::println); // Kobe James Bill
System.out.println("-------------------");
}
}
3. 流的约简
-
Stream<T> distinct ():返回一个流,元素为原来流中的元素剔除重复元素后的结果 -
Stream<T> sorted ():按照自然序就行排列,如String按照字典序排序,数值型按照大小排序,排序的元素要实现Comparable接口 -
Stream<T> sorted (Comparator<? super T> comparator):根据传入的Comparator指定的顺序就行排列,返回一个新的流- 对于数值型数据,程序按数值大小进行排序
- 对于String类型数据,程序按照字典序进行排序
import java.math.BigInteger;
import java.util.*;
import java.util.stream.Stream;
public class SomeMethodsAboutGetStream {
public static void main(String[] args) {
Stream<String> s2 = Stream.of("Forlogen", "Kobe", "James", "Bill", "Forlogen","Forlogen");
s2.distinct().forEach(System.out::println);
System.out.println("-------------------"); // Forlogen Kobe James Bill
Stream<String> s3 = Stream.of("Forlogen", "Kobe", "James", "Bill");
s3.sorted().forEach(System.out::println);
System.out.println("-------------------"); // Bill Forlogen James Kobe
Stream<Integer> s4 = Stream.of(3, 1, 10, 7, 4);
s4.sorted().forEach(System.out::println); // 1 3 4 7 10
System.out.println("-------------------");
Stream<Integer> s5 = Stream.of(3, 1, 10, 7, 4);
s5.sorted(Comparator.comparing(Integer::intValue).reversed()).forEach(System.out::println); // 10 7 4 3 1
System.out.println("-------------------");
}
}
4. 获取流中信息
之前已经学习过通过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)流中存在匹配条件的元素时返回trueboolean allMatch (Predicate<? super T> predicate): 流中任意一个元素都匹配条件时返回trueboolean noneMatch (Predicate<? super T> predicate): 流中没有一个元素匹配条件时返回trueObject[] oArray(): 返回对象数组<A> A[] toArray (IntFunction<A[]> generator):返回A类型的数组Optional<T> reduce (BinaryOperator<T> accumulator):用给定的accumulator产生流中元素的累积总和void forEachOrdered(Consumer<? super T> action): 为该流的每个元素执行一个操作,如果该流具有已定义的相遇顺序,则按照该流的相遇顺序执行
import java.math.BigInteger;
import java.util.*;
import java.util.stream.Stream;
public class SomeMethodsAboutGetStream {
public static void main(String[] args) {
Stream<Integer> s6 = Stream.of(3, 1, 10, 7, 4);
Optional<Integer> min = s6.min(Comparator.comparing(Integer::intValue));
System.out.println(min.get()); // 1
System.out.println("-------------------");
Stream<Integer> s7 = Stream.of(3, 1, 10, 7, 4);
Optional<Integer> max = s7.max(Comparator.comparing(Integer::intValue));
System.out.println(max.get()); // 10
System.out.println("-------------------");
Stream<String> s8 = Stream.of("Forlogen", "Kobe", "James", "Bill", "Forever");
System.out.println(s8.takeWhile(ss -> ss.startsWith("F")).findFirst().get()); // Forlogen
System.out.println("-------------------");
Stream<String> s9 = Stream.of("Forlogen", "Kobe", "James", "Bill", "Forever");
System.out.println(s9.takeWhile(ss -> ss.startsWith("F")).findAny().get()); // Forlogen
System.out.println("-------------------");
Stream<String> s10 = Stream.of("Forlogen", "Kobe", "James", "Bill", "Forever");
Stream<String> s11 = Stream.of("Forlogen", "Kobe", "James", "Bill", "Forever");
Stream<String> s12 = Stream.of("Forlogen", "Kobe", "James", "Bill", "Forever");
System.out.println(s10.anyMatch(s -> s.startsWith("F"))); // true
System.out.println(s11.allMatch(s -> s.startsWith("F"))); // false
System.out.println(s12.noneMatch(s -> s.startsWith("F"))); // false
System.out.println("-------------------");
Stream<String> s13 = Stream.of("Forlogen", "Kobe", "James", "Bill", "Forever");
System.out.println(Arrays.toString(s13.takeWhile(s -> s.startsWith("F")).toArray())); // [Forlogen]
Stream<String> s14 = Stream.of("Forever", "Kobe", "James", "Bill");
System.out.println(Arrays.toString(s14.takeWhile(s -> s.length() > 4).toArray(String[]::new))); // [Forever]
System.out.println("-------------------");
Stream<Object> s15 = Stream.ofNullable(10);
s15.forEach(System.out::println); // 10
System.out.println("-------------------");
Stream<Integer> s16 = Stream.of(3, 1, 10, 7, 4);
System.out.println(s16.reduce(Integer::sum).get()); // 25
System.out.println("-------------------");
Stream<Integer> s17 = Stream.of(3, 1, 10, 7, 4);
s17.forEach(System.out::println);
System.out.println("-------------------");
Stream<Integer> s18 = Stream.of(3, 1, 10, 7, 4);
s18.forEachOrdered(System.out::println);
}
}
5. 完整实验代码
import java.math.BigInteger;
import java.util.*;
import java.util.stream.Stream;
public class SomeMethodsAboutGetStream {
public static void main(String[] args) {
// 创建空流
final Stream<Object> empty = Stream.empty();
empty.forEach(k-> System.out.println(k)); //
System.out.println("-------------------");
// 创建无限流
BigInteger limit = new BigInteger("1000000");
Stream.generate(()->"Hello").limit(5).forEach(k -> System.out.println(k));
Stream.iterate(BigInteger.ZERO, n -> n.add(BigInteger.ONE)).limit(5).forEach(System.out::println);
// System.out.println("-------------------");
// stream()、map()、forEach()
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "Hello", "World");
list.forEach(System.out::println);
Stream<Stream<String>> out = list.stream().map(w -> codePoints(w));
codePoints("World").forEach(System.out::println);
System.out.println("-------------------");
/*
takeWhile()、dropWhile()
takeWhile():产生一个流,流中的元素满足传入的谓词条件
dropWhile():产生一个流,流的元素是当前流中排除不满足谓词条件的元素之外的所有元素
*/
Stream<String> s0 = Stream.of("Forlogen", "Kobe", "James", "Bill", "Forever");
Stream<String> s1 = Stream.of("Forlogen", "Kobe", "James", "Bill");
s0.takeWhile(ss -> ss.startsWith("F")).forEach(System.out::println); // Forlogen
s1.dropWhile(ss -> ss.startsWith("F")).forEach(System.out::println); // Kobe James Bill
System.out.println("-------------------");
/*
Stream<T> distinct ():返回一个流,元素为原来流中的元素剔除重复元素后的结果
*/
Stream<String> s2 = Stream.of("Forlogen", "Kobe", "James", "Bill", "Forlogen","Forlogen");
s2.distinct().forEach(System.out::println);
System.out.println("-------------------"); // Forlogen Kobe James Bill
/*
Stream<T> sorted ():按照自然序就行排列,如String按照字典序排序,数值型按照大小排序
排序的元素要实现Comparable接口
Stream<T> sorted (Comparator<? super T> comparator): 根据传入的Comparator指定的顺序就行排列,返回一个新的流
*/
Stream<String> s3 = Stream.of("Forlogen", "Kobe", "James", "Bill");
s3.sorted().forEach(System.out::println);
System.out.println("-------------------"); // Bill Forlogen James Kobe
Stream<Integer> s4 = Stream.of(3, 1, 10, 7, 4);
s4.sorted().forEach(System.out::println); // 1 3 4 7 10
System.out.println("-------------------");
Stream<Integer> s5 = Stream.of(3, 1, 10, 7, 4);
s5.sorted(Comparator.comparing(Integer::intValue).reversed()).forEach(System.out::println); // 10 7 4 3 1
System.out.println("-------------------");
/*
Optional<T> max(Comparator<? super T> comparator):返回按指定排序规则排序后流中的最小元素
Optional<T> min(Comparator<? super T> comparator):返回按指定排序规则排序后流中的最大元素
*/
Stream<Integer> s6 = Stream.of(3, 1, 10, 7, 4);
Optional<Integer> min = s6.min(Comparator.comparing(Integer::intValue));
System.out.println(min.get()); // 1
System.out.println("-------------------");
Stream<Integer> s7 = Stream.of(3, 1, 10, 7, 4);
Optional<Integer> max = s7.max(Comparator.comparing(Integer::intValue));
System.out.println(max.get()); // 10
System.out.println("-------------------");
/*
Optional<T> findFirst():返回产生这个流的第一个元素
Optional<T> findAny():返回产生这个流的任意一个元素
如果流为空,则返回空的Optional对象
*/
Stream<String> s8 = Stream.of("Forlogen", "Kobe", "James", "Bill", "Forever");
System.out.println(s8.takeWhile(ss -> ss.startsWith("F")).findFirst().get()); // Forlogen
System.out.println("-------------------");
Stream<String> s9 = Stream.of("Forlogen", "Kobe", "James", "Bill", "Forever");
System.out.println(s9.takeWhile(ss -> ss.startsWith("F")).findAny().get()); // Forlogen
System.out.println("-------------------");
/*
boolean anyMatch (Predicate<? super T> predicate): 流中存在匹配条件的元素时返回true
boolean allMatch (Predicate<? super T> predicate): 流中任意一个元素都匹配条件时返回true
boolean noneMatch (Predicate<? super T> predicate): 流中没有一个元素匹配条件时返回true
*/
Stream<String> s10 = Stream.of("Forlogen", "Kobe", "James", "Bill", "Forever");
Stream<String> s11 = Stream.of("Forlogen", "Kobe", "James", "Bill", "Forever");
Stream<String> s12 = Stream.of("Forlogen", "Kobe", "James", "Bill", "Forever");
System.out.println(s10.anyMatch(s -> s.startsWith("F"))); // true
System.out.println(s11.allMatch(s -> s.startsWith("F"))); // false
System.out.println(s12.noneMatch(s -> s.startsWith("F"))); // false
System.out.println("-------------------");
/*
Object[] oArray(): 返回对象数组
<A> A[] toArray (IntFunction<A[]> generator):返回A类型的数组
*/
Stream<String> s13 = Stream.of("Forlogen", "Kobe", "James", "Bill", "Forever");
System.out.println(Arrays.toString(s13.takeWhile(s -> s.startsWith("F")).toArray())); // [Forlogen]
Stream<String> s14 = Stream.of("Forever", "Kobe", "James", "Bill");
System.out.println(Arrays.toString(s14.takeWhile(s -> s.length() > 4).toArray(String[]::new))); // [Forever]
System.out.println("-------------------");
/*
static <T> Stream<T> ofNullable(T t):返回含单个元素的流
*/
Stream<Object> s15 = Stream.ofNullable(10);
s15.forEach(System.out::println); // 10
System.out.println("-------------------");
/*
Optional<T> reduce (BinaryOperator<T> accumulator):用给定的accumulator产生流中元素的累积总和
*/
Stream<Integer> s16 = Stream.of(3, 1, 10, 7, 4);
System.out.println(s16.reduce(Integer::sum).get()); // 25
System.out.println("-------------------");
/*
void forEachOrdered(Consumer<? super T> action): 为该流的每个元素执行一个操作,如果该流具有已定义的相遇顺序,则按照该流的相遇顺序执行。
*/
Stream<Integer> s17 = Stream.of(3, 1, 10, 7, 4);
s17.forEach(System.out::println);
System.out.println("-------------------");
Stream<Integer> s18 = Stream.of(3, 1, 10, 7, 4);
s18.forEachOrdered(System.out::println);
}
public static Stream<String> codePoints(String s){
ArrayList<String> list = new ArrayList<>();
int i = 0;
while (i < s.length()){
int j = s.offsetByCodePoints(i, 1);
list.add(s.substring(i, j));
i = j;
}
return list.stream();
}
}
6. 基本流
之前所有的关于Stream的操作,我们使用的都是java.util.Stream<T>,如果想要将int型的数据存储到流中程序实际上是将其保存到Stream<Integer>,Stream<int>是不存在的,但这样就需要将其转换为对应的包装类型,效率较低。
java.util.stream中有DoubleStream、IntStream和LongStream来直接存储基本类型的值,而无需使用包装类
- IntStream用于存储short、char、byte和boolean类型的数据
- DoubleStream用于存储float、double型数据
基本类型流的创建同样可以使用of()、generate()和iterate()。除此之外,IntStream和LongStream有静态的方法range()、rangeClosed()用于生成步长为1的整数范围
import java.util.Arrays;
import java.util.OptionalDouble;
import java.util.OptionalInt;
import java.util.stream.IntStream;
public class BasicStream {
public static void main(String[] args) {
private static void TestIntStream() {
System.out.println(Arrays.toString(IntStream.of(1, 4, 3, 15).toArray())); // [1, 4, 3, 15]
System.out.println("--------------------");
System.out.println(Arrays.toString(IntStream.range(1, 10).toArray())); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
System.out.println("--------------------");
System.out.println(Arrays.toString(IntStream.rangeClosed(1, 10).toArray())); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
System.out.println("--------------------");
OptionalInt min = IntStream.range(1, 10).min();
System.out.println(min.getAsInt()); // 1
System.out.println("--------------------");
OptionalInt max = IntStream.range(1, 10).max();
System.out.println(max.getAsInt()); // 9
System.out.println("--------------------");
OptionalDouble average = IntStream.range(1, 10).average();
System.out.println(average.getAsDouble()); // 5.0
System.out.println("--------------------");
int sum = IntStream.range(1, 10).sum();
System.out.println(sum); // 45
System.out.println("--------------------");
}
}
}
DoubleStream和LongStream有相似的操作,详细信息可以查看API文档。
7. 并行流
并行流的获取方法:
- 使用
Collection.parallelStream()从任意集合中获取一个并行流 - 使用
parallel()将任意顺序的流转换为并行流