Java8 Stream流编程
Stream 使用一种类似于SQL语句从数据库查询数据的直观方式来提供对 Java 集合运算和表达的高阶抽象。得益于 Lambda 所带来的函数式编程,Stream API 可以极大的提高 Java 程序员的生产力。关于函数式编程可以查看我的另一篇博客 Java 函数式接口。
什么是 Stream 流
A sequence of elements supporting sequential and parallel aggregate operations.
翻译过来就是一个支持串行和并行聚合操作的元素序列:
- 序列中的元素是一个特定类型的对象,Stream 本身并不会存储任何元素,而是按需计算
- 序列的来源可以是集合、数组、I/O channel等
- 聚合操作是类型 SQL 语句的操作,如 fiter, map, distinct, sorted 等
获取 Stream 流
- stream():创建串行流
- parallelStream():创建并行流
Java 数组
// 基本类型数组,使用 Arrays.stream() 获取流,类似的还有 LongStream, DoubleStream
int[] nums = {1, 2, 3}
IntStream intStream = Arrays.stream(arr);
// 对象类型数组,使用 Stream.of() 获取流
String[] array = {"a", "b", "c"};
// Stream.of() 内部还是调用的 Arrays.stream(T[] values)
Stream<String> stream = Stream.of(array);
Java 集合
// 集合类型获取串行流
List<Integer> list = new ArrayList<>();
Stream<Integer> stream = list.stream();
// 集合类型获取并行流
// 方法一:直接获取
// 方法二:从串行流转换
Stream<Integer> parallelStream = list.parallelStream();
Stream<Integer> parallelStream = list.stream().parallel();
Set<Integer> set = new HashSet<>();
Stream<Integer> stream2 = set.stream();
Stack<Integer> stack = new Stack<>();
Stream<Integer> stream3 = stack.stream();
Java Map
Map<String, String> map = new HashMap<>();
Stream<Map.Entry<String, String>> entryStream = map.entrySet().stream();
Stream<String> keyStream = map.keySet().stream();
Stream<String> valueStream = map.valueSet().stream();
Java Stream 的使用
数组元素求和
// 传统做法
int[] nums = {1, 2, 3, 4, 5};
int sum = 0;
for (int num : nums) {
sum += nums;
}
// 使用 Stream 求和
int sum = Arrays.stream(nums).sum();
集合遍历过滤
List<String> list = new ArrayList<>();
list.add("ab");
list.add("abc");
list.add("aefg");
list.add("hijkl");
// 传统方法
List<String> startWithA = new ArrayList<>();
for (String temp : list) {
if (temp.startsWith("a")) {
startWithA.add(temp);
}
}
List<String> longList = new ArrayList<>();
for (String temp : startWithA) {
if (temp.length() >= 4) {
longList.add(temp);
}
}
// Stream 方法
List<String> filtered = list.stream().filter(s -> s.startsWith("a"))
.filter(s -> s.length() >= 4)
.collect(Collectors.toList());
Stream 风格可以使得 Java 代码干净、简洁,这种风格将要处理的元素集合看作一种流,流在管道中传输,并且可以在管道的节点上进行处理。
从上面的例子可以看出 Stream 操作有以下两个特征:
- 中间操作会返回流对象本身,多个操作可以串联成一个管道,如同流式风格
- 传统集合遍历都是通过迭代器或者For-Each的方式在集合外部进行迭代,Stream 提供了内部迭代的方式,通过访问者模式实现
Java Stream 常用方法分析
filter() 方法
将 Stream 流转换成一个子集流。
/**
* Returns a stream consisting of the elements of this stream
* that match the given predicate.
*/
Stream<T> filter(Predicate<? super T> predicate);
// Example
String[] array = {"a", "bc", "def", "ghij"};
Stream<String> stream = Stream.of(array);
// 子集流中包括元素 "def", "ghij"
Stream<String> subStream = stream.filter(s -> s.length() >= 3);
map() 方法
将 Stream 流中的元素映射到另一个流中。
/**
* Returns a stream consisting of the results of applying the given
* function to the elements of this stream.
*/
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
// Example
String[] array = {"a", "bc", "def", "ghij"};
Stream<String> stream = Stream.of(array);
// 流中包括array每个字符串的长度,{1, 2, 3, 4}
Stream<Integer> mapStream = stream.map(s -> s.length());
distinct() 方法
对 Stream 流中的元素做去重处理。
/**
* Returns a stream consisting of the distinct elements (according to
* {@link Object#equals(Object)}) of this stream.
*/
Stream<T> distinct();
// Example
String[] array = {"a", "bc", "def", "bc", "a"};
Stream<String> stream = Stream.of(array);
// "a", "bc" 是重复元素, distinct处理后流中只会保留一个
Stream<String> distinctStream = stream.distinct();
sorted() 方法
对 Stream 流中的元素排序。
/**
* Returns a stream consisting of the elements of this stream, sorted
* according to natural order. If the elements of this stream are
* not{@code Comparable}, a {@code java.lang.ClassCastException} may
* be thrown when the terminal operation is executed.
*/
Stream<T> sorted();
// Example
String[] array = {"a", "cc", "ab", "b", "c"};
Stream<String> stream = Stream.of(array);
// 流中的元素按字典顺序升序排列
// {"a", "ab", "b", "c", "cc"}
Stream<String> sortedStream = stream.sorted();
/**
* Returns a stream consisting of the elements of this stream, sorted
* according to the provided {@code Comparator}.
* 自定义排序规则
*/
Stream<T> sorted(Comparator<? super T> comparator);
// 流中的元素按长度升序排列
// {"a", "b", "c", "ab", "cc"}
Stream<String> sortedStream = stream.sorted((o1, o2) -> o1.length() - o2.length());
limit() 方法
截取流中的元素,取前 maxSize
个元素。
/**
* Returns a stream consisting of the elements of this stream,
* truncated to be no longer than {@code maxSize} in length. Stream<T>
* limit(long maxSize);
*/
Stream<T> limit(long maxSize);
// Example
String[] array = {"a", "cc", "ab", "b", "c"};
Stream<String> stream = Stream.of(array);
// 截取流中前3个元素,{"a", "cc", "ab"}
Stream<String> limitStream = stream.limit(3);
skip() 方法
跳过前 n
个元素,如果原 Stream 流中元素个数小于 n
,则返回一个空的 Stream 流。
/**
* Returns a stream consisting of the remaining elements of this
* stream after discarding the first {@code n} elements of the
* stream.
* If this stream contains fewer than {@code n} elements then an
* empty stream will be returned.
*/
Stream<T> skip(long n);
// Example
String[] array = {"a", "cc", "ab", "b", "c"};
Stream<String> stream = Stream.of(array);
// 跳过流中前3个元素,返回 {"b", "c"}
Stream<String> limitStream = stream.skip(3);
// 跳过流中前5个元素,返回 {}
Stream<String> limitStream = stream.skip(3);
forEach() 方法
将每一个流元素交给 action
中的方法处理。
forEach 与 forEachOrdered
- 串行流,两者的效果一致,都是对流中的元素顺序执行
action
中的操作 - 并行流,
forEach
操作元素不一定按顺序执行,而forEachOrdered
则保证元素按顺序执行
/**
* Performs an action for each element of this stream.
*/
void forEach(Consumer<? super T> action);
/**
* Performs an action for each element of this stream, in the
* encounter order of the stream if the stream has a defined
* encounter order.
*/
void forEachOrdered(Consumer<? super T> action);
// Example
String[] array = {"a", "cc", "ab", "b", "c"};
Stream<String> stream = Stream.of(array);
// 顺序输出流中的元素,{"a", "cc", "ab", "b", "c"}
stream.forEach(s -> System.out.println(s));
stream.forEachOrdered(s -> System.out.println(s));
toArray() 方法
返回一个数组,包含 Stream 流中的元素。
/**
* Returns an array containing the elements of this stream.
*/
String[] array = {"a", "cc", "ab", "b", "c"};
Stream<String> stream = Stream.of(array);
// 将原Stream流中的元素去重后转换为数组
String[] array2 = (String[])stream.distinct().toArray();
min(), max() 方法
分别返回 Stream 流中最小的元素,最大的元素。
/**
* Returns the minimum element of this stream according to the
* provided.
*/
Optional<T> min(Comparator<? super T> comparator);
// Example
List<Integer> list = new ArrayList<>();
list.add(2);
list.add(4);
list.add(1);
list.add(3);
Optional<Integer> min = list.stream().min((o1, o2) -> o1 - o2);
Optional<Integer> max = list.stream().max((o1, o2) -> o1 - o2);
// 1, 4
System.out.println(min.get() + ", " + max.get());
count() 方法
返回 Stream 流中元素的个数。
/**
* Returns the count of elements in this stream.
*/
long count();
List<Integer> list = new ArrayList<>();
list.add(2);
list.add(4);
list.add(1);
list.add(3);
// 4
long numbers = list.stream().count();
anyMatch() 方法
Stream 流中存在元素满足 predicate
中的约束,则返回 True
。
/**
* Returns whether any elements of this stream match the provided
* predicate.
*/
boolean anyMatch(Predicate<? super T> predicate);
// Example
List<Integer> list = new ArrayList<>();
list.add(2);
list.add(4);
list.add(1);
list.add(3);
boolean flag1 = list.stream().anyMatch(num -> num > 2); // True
boolean flag2 = list.stream().anyMatch(num -> num > 4); // False
allMatch() 方法
Stream 流中所有元素满足 predicate
中的约束,则返回 True
。
/**
* Returns whether all elements of this stream match the provided
* predicate.
*/
boolean allMatch(Predicate<? super T> predicate);
// Example
List<Integer> list = new ArrayList<>();
list.add(2);
list.add(4);
list.add(1);
list.add(3);
boolean flag1 = list.stream().allMatch(num -> num > 0); // True
boolean flag2 = list.stream().allMatch(num -> num > 2); // False
concat() 方法
合并两个 Stream 流中的元素。
/**
* Creates a lazily concatenated stream whose elements are all the
* elements of the first stream followed by all the elements of the
* second stream.
*/
public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b) {
Objects.requireNonNull(a);
Objects.requireNonNull(b);
@SuppressWarnings("unchecked")
Spliterator<T> split = new Streams.ConcatSpliterator.OfRef<>(
(Spliterator<T>) a.spliterator(), (Spliterator<T>) b.spliterator());
Stream<T> stream = StreamSupport.stream(split, a.isParallel() || b.isParallel());
return stream.onClose(Streams.composedClose(a, b));
}
// Example
String[] s1 = {"a", "c", "e"};
String[] s2 = {"b", "d", "f"};
// {"a", "c", "e", "b", "d", "f"}
Stream.concat(Stream.of(s1), Stream.of(s2)).forEach(s -> System.out.println(s));
参考文章
[1] Java-Stream流详解
标签:Java,Stream,stream,元素,list,add,array From: https://www.cnblogs.com/ylyzty/p/16717368.html