Java Stream 编程

Java Stream 编程

教程:https://www.bilibili.com/video/BV1te411w722

1. 不可变集合

1.1 不可变集合应用场景

元数据,只允许查询的数据集合

1.2 创建不可变集合

List、Set、Map 接口中的静态方法 of()

List<String> list = List.of("张三", "李四", "王五");

Set<String> set = Set.of("A", "B", "C");

Map<String, String> map = Map.of("k1", "v1", "k2", "v2");

对不可变集合进行修改时会报错:

Map<String, String> map = Map.of("k1", "v1", "k2", "v2");
map.put("k1", "v2");

在这里插入图片描述

Note:
当创建不可变 Set 或者 Map 时,不能有重复的元素和相同的 Key
Map 里面的 of 参数有上限,最多 10 个键值对!(因为一个函数不能有多个可变参数)

由于 Mapof 方法最多只能有 10 个键值对,引入 ofEntries 方法和 copyOf

1.2.1 Map.ofEntries 方法
Map<String, String> map = Map.ofEntries(
               Map.entry("k1", "v1"),
               Map.entry("k2", "v2"),
               Map.entry("k3", "v3"),
               Map.entry("k4", "v4"));
Map<String, Integer> hashMap = new HashMap<>();
hashMap.put("mary", 1);
hashMap.put("jack", 2);
hashMap.put("mike", 3);
// toArray 方法在底层会比较集合的长度和数组的长度两者的大小
// 若集合长度 > 数组的长度,数组在数组中放不下,此时会根据实际数据的个数重新创建数组
// 若集合长度 <= 数组的长度,数据在数组中放得下,此时不会创建新的数组,而是直接使用
Map<String, Integer> entries = Map.ofEntries(hashMap.entrySet().toArray(new Map.Entry[0]));
entries.forEach((k, v) -> System.out.println(k + ":" + v));
1.2.2 Map.copyOf 方法(JDK 10)
Map<String, Integer> hashMap = new HashMap<>();
hashMap.put("mary", 1);
hashMap.put("jack", 2);
hashMap.put("mike", 3);
Map.copyOf(hashMap)

2. Stream 流

2.1 小需求

在这里插入图片描述

List<String> list = new ArrayList<>();
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张强");
list.add("张三丰");

list.stream()
.filter(name -> name.startsWith("张"))
.filter(name -> name.length() == 3)
.forEach(System.out::println);

2.2 Stream 的思想

把要操作的步骤放在一个流水线上

2.3 Stream 的作用

结合 Lambda 表达式,简化集合、数组的操作

2.4 Stream 的使用步骤

  1. 先得到一条 Stream,并把数据放上去
  2. 利用 Stream 中的 API 进行各种操作(中间方法和终结方法)
2.4.1 获取 Stream

在这里插入图片描述

// 1. 单列集合
List<String> list = new ArrayList<>();
Collections.addAll(list, "A", "B", "C", "D");
list.stream().forEach(System.out::println);

// 2. 双列集合
Map<String, Integer> map = new HashMap<>();
map.put("Mary", 1);
map.put("Mike", 2);
map.put("Jack", 3);
map.put("Rose", 4);
map.entrySet().stream().forEach(System.out::println);
map.forEach((k, v) -> System.out.println(k + " <=> " + v));

// 3. 数组
int[] arr = {1, 2, 3, 4};
Arrays.stream(arr).forEach(System.out::println);

// 4. 零散数据
Stream.of("Hello", 111, "World").forEach(System.out::println);

Note:
Stream.of 方法使用细节,方法的参数可以传递数组,但是数组必须是引用类型,若传递基本数据类型的数组会把整个数组当作一个元素放在 stream 中。

2.4.2 Stream 的中间方法

在这里插入图片描述

Note:

  • 中间方法会返回新的 Stream 流,原来的 Stream 流只能使用一次,建议使用链式编程
  • 修改 Stream 中的数据,不会影响原来集合或者数组中的数据
List<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张强", "张三丰");
Stream<String> stream1 = list.stream();
Stream<String> stream2 = stream1.filter(name -> name.startsWith("张"));
Stream<String> stream3 = stream1.filter(name -> name.length() == 3);

在这里插入图片描述

2.4.2.1 filter 过滤

使用过滤条件

2.4.2.2 skip 跳过 / limit 取前几个

skip 表示跳过几个元素,limit 表示取前几个元素:

List<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张强", "张三丰");
list.stream().skip(2).limit(2).forEach(System.out::println);

在这里插入图片描述

2.4.2.3 distinct 去重
List<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌", "张无忌", "张无忌", "周芷若", "周芷若", "赵敏", "张强", "张三丰");
list.stream().distinct().forEach(log::info);

在这里插入图片描述

底层使用了 HashSet,因此依赖 hashCodeequals 方法。

2.4.2.4 concat 合并
List<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张强", "张三丰");

List<String> list2 = new ArrayList<>();
Collections.addAll(list2, "白眉鹰王", "金毛狮王");

Stream.concat(list.stream(), list2.stream()).forEach(log::info);

在这里插入图片描述

2.4.2.5 map 转换数据类型
List<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌-14", "周芷若-13", "赵敏-13", "张强-20", "张三丰-100");
list.stream().map(s -> Integer.parseInt(s.split("-")[1])).forEach(s -> log.info("{}", s));

在这里插入图片描述

2.4.3 Stream 的终结方法

在这里插入图片描述

2.4.3.1 forEach 遍历

遍历元素

2.4.3.2 count 统计
List<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张强", "张三丰");
log.info("{}", list.stream().count());
log.info("{}", list.stream().filter(name -> name.startsWith("张")).count());

在这里插入图片描述

2.4.3.3 toArray 转换为数组
List<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张强", "张三丰");
// 这里面的 value 表示数组长度, 默认已经得到了
String[] arr = list.stream().toArray(value -> new String[value]);
//        String[] arr = list.stream().toArray(String[]::new);
log.info(Arrays.toString(arr));

在这里插入图片描述

Note:
空参 toArray 方法会默认使用数组 Object[]

2.4.3.4 collect 收集为集合

转换为 List 集合:

List<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌-男-14", "周芷若-女-13", "赵敏-女-13", "张强-男-20", "张三丰-男-100");
List<String> newList = list.stream()
        .filter(s -> "男".equals(s.split("-")[1]))
        .collect(Collectors.toList());
newList.forEach(log::info);

//        List<String> newList = list.stream()
//                .filter(s -> "男".equals(s.split("-")[1])).toList();

在这里插入图片描述

转换为 Set 集合:

List<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌-男-14", "周芷若-女-13", "赵敏-女-13", "张强-男-20", "张三丰-男-100");
Set<String> set = list.stream()
        .filter(s -> "男".equals(s.split("-")[1])).collect(Collectors.toSet());
log.info(set.toString());

在这里插入图片描述

转换为 Map(注意 key 不能重复):

List<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌-男-14", "周芷若-女-13", "赵敏-女-13", "张强-男-20", "张三丰-男-100");
Map<String, Integer> map = list.stream()
        .filter(s -> "男".equals(s.split("-")[1]))
        .collect(Collectors.toMap(s -> s.split("-")[0], s -> Integer.parseInt(s.split("-")[2])));
map.forEach((k, v) -> log.info("{} <=> {}", k, v));

在这里插入图片描述

2.5 Stream 排序

2.5.1 Map 排序

Map<String, String> map = Map.ofEntries(
                Map.entry("Mary", "15"),
                Map.entry("Amy", "16"),
                Map.entry("Jack", "13"),
                Map.entry("Rose", "14"));
                
// 根据 key 正序排序
map.entrySet().stream().sorted(Map.Entry.comparingByKey()).forEach(System.out::println);

// 根据 value 正序排序
map.entrySet().stream().sorted(Map.Entry.comparingByValue()).forEach(System.out::println);

// 根据 key 倒序排序
map.entrySet().stream().sorted(Collections.reverseOrder(Map.Entry.comparingByKey())).forEach(System.out::println);

// 根据 value 倒序排序
map.entrySet().stream().sorted(Collections.reverseOrder(Map.Entry.comparingByValue())).forEach(System.out::println);

2.5.2 List 排序

Random random = new Random();
List<Integer> list = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
    list.add(random.nextInt(100));
}

// 默认正序
list.stream().sorted().forEach(System.out::println);
// 倒序
list.stream().sorted((o1, o2) -> o2 - o1).forEach(System.out::println);
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

哇咔咔负负得正

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

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

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

打赏作者

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

抵扣说明:

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

余额充值