Stream流
# 概述
Stream流 是针对集合迭代器的增强
能够自由使用表达式进行控制集合数据
**应用步骤 : **
- 创建 流对象
- 处理 流对象
- 导出 流集合
# 创建 Stream流
有三种不同创建方式 :
元素组分类 | 方法 | 说明 | |
---|---|---|---|
1 | 集合 | Steam<E> stream() | Collection 自带方法 |
2 | 数组 | Arrays.stream(T[] array) | 数组工具类静态方法实现 |
3 | Stream 静态方法 | Stream.stream(T... values) | 零散数据 特定接口实现 |
集合
Arrays.asList(1,2,3,4).stream();
其他集合如此
数组
数组 通过 ==Arrays.stream()== 静态方法实现 流转化
Arrays.stream(new int[]{1,2,3,4})
其他
零散数据 通过 ==Stream.of()== 静态方法实现 流转化
Stream.of(1, 2, 3);
哈希
Map不能直接进行 Stream流转化 , 需要将数据进行降维 , 类单列集合 才可使用
Map<String,String> map = new HashMap<>();
map.put("aaa","111");
map.put("bbb","222");
map.put("ccc","333");
// 降维转化
// 方式1 将key降维
map.keySet().stream();
// 方式2 以 Entry单列 降维
map.entrySet().stream();
# 处理 Stream流
进行对流 数据进行加工(又称中间操作) . 在Stream流中进行操作的数据不会对原集合数据造成影响
**特性 : **
- 不会存储数据
- 不会改变数据
- 不能重复使用 (建议链式调用)
特性测试
@Test
public void test() {
/* 不会改变数据 */
List<Integer> list = Arrays.asList(1, 2, 2, 3, 4, 4, 5);
List<Integer> collect = list.stream().distinct().collect(Collectors.toList());
// list = [1, 2, 2, 3, 4, 4, 5]
System.out.println("list = " + list);
// collect = [1, 2, 3, 4, 5]
System.out.println("collect = " + collect);
}
@Test
public void test2() {
/* 流不能复用*/
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
stream.filter(val -> val > 2);
// 下面会报错
Stream<Integer> skip = stream.skip(2);
//stream1.forEach(System.out::println);
skip.forEach(System.out::println);
}
方法 :
返回 | 方法 | 说明 |
---|---|---|
Stream<T> | ==filter(Predicate<T> predicate)== | 过滤 |
Stream<T> | ==limit(long maxSize)== | 获取前N个元素 |
Stream<T> | ==skip(long n)== | 跳过前N个元素获取 |
Stream<T> | ==distinct()== | 元素去重 |
static Stream<T> | ==concat(Stream a, Stream b)== | 合并a和b两个流 |
Stream<R> | ==map(Function<T, R> mapper)== | 转换流类型 |
详细就不测试了
# 导出 Stream流
进行对流 进行 遍历/统计/集合/数组 的导出 , 专门针对加工后的 Stream进行导出 (最终操作)
导出方式 :
- 直接遍历
- 总数统计
- 集合/数组 导出
- get导出 (用于Optional中存在一个值的时候)
**方法 : **
返回 | 方法 | 说明 |
---|---|---|
void | ==forEach(Consumer action)== | 遍历 |
long | ==count()== | 统计 |
- | ==toArray(IntFunction<A[]> generator)== | 数组导出 |
- | ==collect(Collector collector)== | 集合导出 |
List<Integer> list = Arrays.asList(1, 2, 2, 3, 4, 4, 5);
// 懂得都懂
//list.forEach(System.out::print);
// 计算总数
System.out.println("count = " + list.stream().count()); // count = 7
// 数组 导出
Integer[] ints = list.stream().distinct().toArray(Integer[]::new);
System.out.println("ints = " + Arrays.toString(ints)); // ints = [1, 2, 3, 4, 5]
// 集合 导出
List<Integer> collect = list.stream().distinct().collect(Collectors.toList());
System.out.println("collect = " + collect); // [1, 2, 3, 4, 5]
集合/数据 导出方式 携带的参数是指定导出不同类型的 数组/集合 !
Map导出
流需要以Map导出 , 需要自行定义 K/V 的指向 . ==Collectors.toMap(K , V)==
List<String> list = Arrays.asList("aaa-111", "bbb-222", "ccc-333");
Map<String, String> map = list.stream().collect(Collectors.toMap(
str -> str.split("-")[0],
str -> str.split("-")[1]
));
map.forEach((k,v) ->{
System.out.println(k+" : "+v);
});
/* map存储是无序的
aaa : 111
ccc : 333
bbb : 222
*/
分组导出
流需要以集合中的指定类型进行分组 , ==Collectors.groupingBy(val)==
// 对象结构
@Data
@ToString
@AllArgsConstructor
public static class Animals {
private String type;
private String name;
}
@Test
public void test() {
List<Animals> list = new ArrayList<>();
list.add(new Animals("dog", "大汪"));
list.add(new Animals("cat", "桃花"));
list.add(new Animals("dog", "猎豹"));
list.add(new Animals("cat", "梅梅"));
Map<String, List<Animals>> map = list.stream().collect(Collectors.groupingBy(Animals::getType));
map.forEach((k, v) -> {
System.out.println(k + " ==> ");
for (Animals animals : v) {
System.out.println("animals => " + animals);
}
});
}
/** 结果
* cat ==>
* animals => Animals(type=cat, name=桃花)
* animals => Animals(type=cat, name=梅梅)
* dog ==>
* animals => Animals(type=dog, name=大汪)
* animals => Animals(type=dog, name=猎豹)
*/
# 实战场景
# 类型转换
集合 数据类型的转换
List<User> list = new ArrayList();
// list 存数据img...
List<UserVO> listVO = list.stream().map(user -> {
UserVO userVO = new UserVO;
BeanUtils.copyProperties(user, userVO);
return userVO;
}).collect(Collectors.toList());