5.1 Stream介绍和实战

Stream介绍和实战

1. Stream简介

1.1 官方说明

Stream官方地址,简单说Stream可以对集合进行各种非常高效的操作,配合上Lambda表达式,让代码更简洁。

1.2 语法

例如:

 int sum = widgets.stream()
                  .filter(b -> b.getColor() == RED)
                  .mapToInt(b -> b.getWeight())
                  .sum();
我们使用widgets,一个Collection<Widget>,作为流的源,并在流上执行过滤-映射-归约操作,以获得红色小部件的重量总和。(求和是归约操作的一个示例。)

1.3 特点

该包引入的关键抽象是流(stream)。Stream、IntStream、LongStream 和 DoubleStream 这些类是对象和原始 int、long 和 double 类型的流。流与集合在几个方面有所不同:

    1. 无存储。流不是存储元素的数据结构;相反,它通过计算操作的管道,从数据结构、数组、生成器函数或 I/O 通道等源传递元素。
    2. 函数式特性。对流的操作会产生结果,但不会修改其源。例如,对从集合获取的流进行过滤会生成一个新的流,而不是从源集合中删除元素。
    3. 寻求惰性。许多流操作,如过滤、映射或去重,可以实现惰性执行,从而提供优化机会。例如,“找到具有三个连续元音字母的第一个字符串”不需要检查所有输入字符串。流操作分为中间(生成流)操作和终端(产生值或副作用)操作。中间操作总是惰性执行。
    4. 可能无界。集合具有有限大小,而流则不一定。诸如 limit(n) 或 findFirst() 之类的短路操作可以使对无限流的计算在有限时间内完成。
    5. 可消费。流的元素在流的生命周期内只被访问一次。与迭代器类似,要重新访问源的相同元素,必须生成一个新的流。

2. 组成

一个stream操作主要有3个部分:源头、中间操作、终止操作。
中间操作可以有0个或多个,但不是立马执行的,只有终止操作被调用后中间操作才会一起执行(惰性执行)

2.1 源头

一般有

数组
int[] demoArr = new int[]{2,4,6,1};
Arrays.stream(demoArr);
Stream.of(demoArr);

集合Collection
List<Object> demoList = new ArrayList<>();
demoList.stream();
Stream.of(demoList);;

2.2 中间操作

一般有

filter      条件过滤
map         对流中的每个元素按照指定的映射规则进行转换
flatmap     将每个元素映射成一个流,然后将所有流合并成一个流的方法。这个方法通常用于将嵌套的集合展开成一个扁平的流。
sorted      按照规则排序
skip        跳过指定数量的元素,返回一个包含剩余元素的新流
limit       数量限制
distinct    去重

2.3 终止操作

一般有

reduce
foreach
collect
allMatch
anyMatch
noneMatch
findFirst
findAny
max
min
count

3. 案例

3.1 中间操作案例

通用参数

List<User> userList = new ArrayList<>();
User userYang = new User("1", "小杨", 18);
userList.add(userYang);
User userWang = new User("2", "小王", 16);
userList.add(userWang);
User userLi = new User("3", "小李", 20);
userList.add(userLi);
List<String> list1 = Arrays.asList("hello", "world");
List<String> list2 = Arrays.asList("java", "stream");
1. filter过滤
userList.stream()
        .filter(item -> item.getCode().equals("1"))
        .forEach(item -> {
            System.out.println(item.getName());
        });

输出: 小杨
2.1. map用法1,提取code
List<String> codeList = userList.stream().map(User::getCode).collect(Collectors.toList());
System.out.println(JSON.toJSONString(codeList));

输出: ["1","2","3"]
2.2. map用法2,便利修改当前对象,不产生新对象
userList.stream().map(item -> {
    item.setAge(18);
    return item;
}).collect(Collectors.toList());
System.out.println(JSON.toJSONString(userList));

输出: [{"age":18,"code":"1","name":"小杨"},{"age":18,"code":"2","name":"小王"},{"age":18,"code":"3","name":"小李"}]
3. flatMap,将一个Stream中的每个元素转换为另一个Stream,然后将所有转换后的Stream合并为一个新的Stream
List<String> result = Stream.of(list1, list2)
        .flatMap(Collection::stream)
        .collect(Collectors.toList());
System.out.println(result);

输出: [hello, world, java, stream]
4. sort
List<User> sortUserList = userList.stream().sorted(Comparator.comparing(User::getAge)).collect(Collectors.toList());
System.out.println(JSON.toJSONString(sortUserList));

输出: [{"age":16,"code":"2","name":"小王"},{"age":18,"code":"1","name":"小杨"},{"age":20,"code":"3","name":"小李"}]
5. skip
List<User> skipUserList = userList.stream().skip(1).collect(Collectors.toList());
System.out.println(JSON.toJSONString(skipUserList));

输出: [{"age":16,"code":"2","name":"小王"},{"age":20,"code":"3","name":"小李"}]
6. limit
List<User> limitUserList = userList.stream().limit(1).collect(Collectors.toList());
System.out.println(JSON.toJSONString(limitUserList));

输出: [{"age":18,"code":"1","name":"小杨"}]
7. distinct
User userLiCopy = new User("3", "小李", 20);
userList.add(userLiCopy);
List<User> distinctUserList = userList.stream().distinct().toList();
System.out.println(JSON.toJSONString(distinctUserList));

输出: 添加一个重复元素之后去重, [{"age":18,"code":"1","name":"小杨"},{"age":16,"code":"2","name":"小王"},{"age":20,"code":"3","name":"小李"}]

3.2 终止操作案例

1. reduce:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream().reduce(0, (acc, x) -> acc + x);
System.out.println("Sum of numbers: " + sum);

输出: Sum of numbers: 15
2. foreach:
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.stream().forEach(System.out::println);

输出: 
 Alice
 Bob
 Charlie
3. collect:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> squares = numbers.stream().map(x -> x * x).collect(Collectors.toList());
System.out.println("Squares of numbers: " + squares);

输出: Squares of numbers: [1, 4, 9, 16, 25]
4. allMatch:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean allEven = numbers.stream().allMatch(x -> x % 2 == 0);
System.out.println("Are all numbers even? " + allEven);

输出:  Are all numbers even? false
5. anyMatch:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean anyEven = numbers.stream().anyMatch(x -> x % 2 == 0);
System.out.println("Are there any even numbers? " + anyEven);

输出: Are there any even numbers? true
6. noneMatch:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean noneNegative = numbers.stream().noneMatch(x -> x < 0);
System.out.println(noneNegative);

输出: true
7. findFirst:
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
Optional<String> first = names.stream().findFirst();
System.out.println("First name: " + first.orElse("None"));

输出: First name: Alice
8. findAny:
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
Optional<String> any = names.stream().findAny();
System.out.println("Any name: " + any.orElse("None"));

输出: Any name: Alice
9. max:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> maxNum = numbers.stream().max(Integer::compare);
System.out.println("Max number: " + maxNum.orElse(0));

输出: Max number: 5
10. min:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> minNum = numbers.stream().min(Integer::compare);
System.out.println("Min number: " + minNum.orElse(0));

输出: Min number: 1
11. count:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
long count = numbers.stream().count();
System.out.println("Number of elements: " + count);

输出:Number of elements: 5
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鱼鱼大头鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值