概念
Stream(流)是一个来自数据源的元素队列并支持聚合操作
元素是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算。
数据源 流的来源。 可以是集合,数组,I/O channel, 产生器generator 等。
聚合操作 类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等。
和以前的Collection操作不同, Stream操作还有两个基础的特征:
Pipelining: 中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道, 如同流式风格(fluent style)。 这样做可以对操作进行优化, 比如延迟执行(laziness)和短路( short-circuiting)。
内部迭代: 以前对集合遍历都是通过Iterator或者For-Each的方式, 显式的在集合外部进行迭代, 这叫做外部迭代。 Stream提供了内部迭代的方式, 通过访问者模式(Visitor)实现。
开始
获取流
List<BsInfo> list = new ArrayList<>();
//获取串行流
Stream<BsInfo> stream = list.stream();
//获取并行流
Stream<BsInfo> parallelStream = list.parallelStream();
循环 forEach(Consumer<? super T> action)
//循环打印
Arrays.asList("aa", "", "ab", "34", "bva")
.stream().forEach(System.out::println);
过滤 filter(Predicate<? super T> predicate)
Arrays.asList("aa", "", "ab", "34", "bva")
.stream().filter(p->p.contains("a"))//保留结果为true的
.forEach(System.out::println);
打印结果
aa
ab
bva
去重 distinct()
Arrays.asList("aa", "", "ab", "ab","bva").stream().
distinct().forEach(System.out::println);
打印结果
aa
ab
bva
排序 sorted()
Arrays.asList("aa", "", "ab", "ab","bva").stream().
sorted().forEach(System.out::println);
打印结果
aa
ab
ab
bva
自定义规则排序 sorted(Comparator<? super T> comparator)
List<Person> list = new ArrayList<>();
list.add(new Person("张三",12,"男"));
list.add(new Person("王五",32,"男"));
list.add(new Person("李四",22,"男"));+
list.add(new Person("小红",18,"女"));
list.stream().sorted((p1,p2) -> p1.getAge()-p2.getAge())
.forEach(System.out::println);
//或者写成
list.stream().sorted(Comparator.comparingInt(Person::getAge))
.forEach(System.out::println);
打印结果
Person [age=12, name=张三, sex=男]
Person [age=18, name=小红, sex=女]
Person [age=22, name=李四, sex=男]
Person [age=32, name=王五, sex=男]
截取 limit(long n)保留前N个 、skip(long n)去除前N个
//保留前3个
Arrays.asList("aa", "vv", "ab", "ab", "bva").stream().limit(3)
.forEach(p->System.out.print(p+"-"));
// 结果 aa-vv-ab-
//去除前3个
Arrays.asList("aa", "vv", "ab", "ab", "bva").stream().skip(3)
.forEach(p->System.out.print(p+"-"));
// 结果 ab-bva-
//先去除前1个,再在剩下的中保留前2个
Arrays.asList("aa", "vv", "ab", "ab", "bva").stream().skip(1).limit(2)
.forEach(p->System.out.print(p+"-"));
// 结果 vv-ab-
//先保留前3个,再在剩下的中去除前2个
Arrays.asList("aa", "vv", "ab", "ab", "bva").stream().limit(3).skip(2)
.forEach(p->System.out.print(p+"-"));
// 结果 ab-
合并 flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)
List<List<Integer>> ll = new ArrayList<>();
ll.add(Arrays.asList(7,5,3));
ll.add(Arrays.asList(1,9,4));
ll.add(Arrays.asList(2,8,6));
//[[7, 5, 3], [1, 9, 4], [2, 8, 6]]
List<Integer> collect = ll.stream().flatMap(List::stream)
.collect(Collectors.toList());
//[7, 5, 3, 1, 9, 4, 2, 8, 6]
List<Integer> collect = ll.stream().flatMap(List::stream).sorted()
.collect(Collectors.toList());
//[1, 2, 3, 4, 5, 6, 7, 8, 9]
判断 allMatch(Predicate<? super T> predicate) 、noneMatch(Predicate<? super T> predicate) 、anyMatch(Predicate<? super T> predicate)
List<Person> list = new ArrayList<>();
list.add(new Person("张三",12,"男"));
list.add(new Person("王五",32,"男"));
list.add(new Person("李四",22,"男"));
list.add(new Person("小红",18,"女"));
//年龄全部小于30
boolean allMatch = list.stream().allMatch(p->p.getAge()<30);//false
//有任意一个年龄小于30
boolean anyMatch = list.stream().anyMatch(p->p.getAge()<30);//true
//没有年龄小于30
boolean noneMatch = list.stream().noneMatch(p->p.getAge()<30);//false
转换 map(Function<? super T, ? extends R> mapper)
List<Person> list = new ArrayList<>();
list.add(new Person("张三",12,"男"));
list.add(new Person("王五",32,"男"));
list.add(new Person("李四",22,"男"));
list.add(new Person("小红",18,"女"));
//有Person类型的流转换为String类型的
list.stream().map(Person::getName).forEach(n->System.out.println(n));
打印结果
张三
王五
李四
小红
收集 collect(Collector<? super T, A, R> collector)
List<Person> list = new ArrayList<>();
list.add(new Person("张三",12,"男"));
list.add(new Person("王五",32,"男"));
list.add(new Person("李四",22,"男"));
list.add(new Person("小红",18,"女"));
//将流转换为List
List<String> collect = list.stream().map(Person::getName)
.collect(Collectors.toList());
//[张三, 王五, 李四, 小红]
Set<String> collect2 = list.stream().map(Person::getName)
.collect(Collectors.toSet());
//[李四, 张三, 王五, 小红]
Map<String, String> collect3 = list.stream()
.collect(Collectors.toMap(Person::getName,Person::getSex));
//{李四=男, 张三=男, 王五=男, 小红=女}
Map<String, Person> collect4 = list.stream()
.collect(Collectors.toMap(Person::getName,(p)->p));
//{李四=Person [age=22, name=李四, sex=男], 张三=Person [age=12, name=张三, sex=男], 王五=Person [age=32, name=王五, sex=男], 小红=Person [age=18, name=小红, sex=女]}
//Function.identity() 返回对象本身,就相当于(p)->p
Map<String, Person> collect4 = list.stream()
.collect(Collectors.toMap(Person::getName,Function.identity()));
一点点补充
去重
上面distinct()去重对一些字符串,数字集合处理还可以但不能对对象去重,下面补充两种去重方法。
两种都是通过Map去重,但第一种去重保留的是第一次出现的对象,第二种可以指定保留第一次还是最后一次
第一种
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
public class Test {
public static void main(String[] args) {
List<Person> list = new ArrayList<>();
list.add(new Person("张三",12,"男"));
list.add(new Person("王五",32,"男"));
list.add(new Person("李四",22,"男"));
list.add(new Person("李四",78,"男"));
list.add(new Person("小红",18,"女"));
List<Person> collect2 = list.stream().filter(distinctByKey(Person::getName)).collect(Collectors.toList());
//[Person [age=12, name=张三, sex=男], Person [age=32, name=王五, sex=男], Person [age=22, name=李四, sex=男], Person [age=18, name=小红, sex=女]]
}
public static <T> Predicate<T> distinctByKey2(Function<? super T, Object> keyExtractor) {
Map<Object, Boolean> seen = new ConcurrentHashMap<>();
return t -> seen.put(keyExtractor.apply(t), Boolean.TRUE);
}
}
第二种
List<Person> list = new ArrayList<>();
list.add(new Person("张三",12,"男"));
list.add(new Person("王五",32,"男"));
list.add(new Person("李四",22,"男"));
list.add(new Person("李四",78,"男"));
list.add(new Person("小红",18,"女"));
//(k, v) -> v) KEY冲突时,指定保留哪一个
List<Person> collect = list.stream()
.collect(Collectors.toMap(Person::getName, (p) -> p, (k, v) -> v))
.values().stream()
.collect(Collectors.toList());
//[Person [age=78, name=李四, sex=男], Person [age=12, name=张三, sex=男], Person [age=32, name=王五, sex=男], Person [age=18, name=小红, sex=女]]
}
本文深入探讨Java Stream API的基本概念与操作,包括过滤、排序、去重、转换及收集等核心功能。通过实例演示如何简化集合操作,提高代码效率与可读性。
2279

被折叠的 条评论
为什么被折叠?



