实际项目Java1.8流处理, Optional常见用法

流处理

相信大家肯定遇到过列表需要按某个字符进行排序, 这时我们用流处理就可以很优雅的实现该功能了

java 复制代码
convert.setItems(convert.getItems().stream()
    .sorted(Comparator.comparing(
        item -> StringUtils.defaultIfBlank(item.getWarehouseName(), ""),
        Collator.getInstance(Locale.CHINESE)
    ))
    .collect(Collectors.toList()));

解释

  1. StringUtils.defaultIfBlank

    • StringUtils.defaultIfBlank(item.getWarehouseName(), "") 会返回 item.getWarehouseName() 如果它不是空或 null,否则返回空字符串 ""
  2. Comparator.comparing

    • Comparator.comparing 方法用于创建一个比较器,这里使用 Collator.getInstance(Locale.CHINESE) 来确保中文字符的正确排序。
  3. collect(Collectors.toList())

    • 将排序后的流收集为一个新的列表,并设置回 convert 对象的 items 属性。

或者在列表中对手机号进行加密等操作

java 复制代码
                // 手机号加密
                List<GetPackageListRes.GetPackageListInnerPackage> items = convert.getItems().stream()
                        .peek(item -> item.setSenderMobile(StringUtils.isBlank(item.getSenderMobile()) ? "" : AppAesUtils.aesEncrypt(item.getSenderMobile())))
                        .collect(Collectors.toList());

在Java 8的Stream API中,peekmap 是两个常用的中间操作方法,它们的功能和用途有所不同。下面是它们的区别和用法示例:

peek 方法

用途
  • peek 主要用于调试目的,它允许你在流的处理过程中打印或检查每个元素,而不改变元素本身。
  • peek 不会对流中的元素进行任何转换或修改,它只是提供了一个钩子,让你可以在流的处理过程中插入一些操作(通常是日志记录或断言)。
方法签名
java 复制代码
Stream<T> peek(Consumer<? super T> action)
示例
java 复制代码
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

List<Integer> result = numbers.stream()
                             .peek(System.out::println)  // 打印每个元素
                             .filter(n -> n % 2 == 0)
                             .collect(Collectors.toList());

System.out.println(result);  // 输出: [2, 4]

在这个示例中,peek 用于打印流中的每个元素,但不会改变它们。最终的结果是 [2, 4]

map 方法

用途
  • map 用于将流中的每个元素转换为另一个形式。它接受一个函数作为参数,并将该函数应用于流中的每个元素,生成一个新的流。
  • map 是一种转换操作,它可以改变流中元素的类型或值。
方法签名
java 复制代码
<R> Stream<R> map(Function<? super T, ? extends R> mapper)
示例
java 复制代码
List<String> words = Arrays.asList("apple", "banana", "cherry");

List<Integer> lengths = words.stream()
                             .map(String::length)  // 将每个字符串转换为其长度
                             .collect(Collectors.toList());

System.out.println(lengths);  // 输出: [5, 6, 6]

在这个示例中,map 将每个字符串转换为其长度,生成一个新的流,最终的结果是 [5, 6, 6]

总结

  • peek

    • 用于调试,不改变流中的元素。
    • 主要用于在流的处理过程中插入一些操作,如打印日志。
    • 返回类型与输入类型相同。
  • map

    • 用于转换,可以改变流中的元素。
    • 接受一个函数作为参数,将该函数应用于流中的每个元素。
    • 返回类型可以与输入类型不同。

示例对比

假设我们有一个列表,包含一些 GetSelfPickupAddressesListRes 对象,我们希望在处理过程中打印每个对象,并根据 selfPickupType 修改 receiverAddr

使用 peekmap
java 复制代码
List<GetSelfPickupAddressesListRes> listRes = ...; // 初始化列表

List<GetSelfPickupAddressesListRes> processedListRes = listRes.stream()
                                                             .peek(res -> System.out.println("Processing: " + res))
                                                             .map(res -> {
                                                                 if (GetSelfPickupAddressesListRes.SELF_PICKUP_TYPE_CABINET.equals(res.getSelfPickupType())) {
                                                                     res.setReceiverAddr(res.getReceiverAddr() + "(自提柜)");
                                                                 } else if (GetSelfPickupAddressesListRes.SELF_PICKUP_TYPE_POINT.equals(res.getSelfPickupType())) {
                                                                     res.setReceiverAddr(res.getReceiverAddr() + "(自提点)");
                                                                 }
                                                                 return res;
                                                             })
                                                             .collect(Collectors.toList());

// 打印处理后的结果
processedListRes.forEach(System.out::println);

在这个示例中:

  • peek 用于在处理每个对象时打印一条消息。
  • map 用于根据 selfPickupType 修改 receiverAddr

通过这种方式,你可以同时使用 peek 进行调试,并使用 map 进行转换。

Optional常见用法

在日常项目开发中, 我们少不了对应信息进行脱敏加密, 如果对应信息从服务调用而来, 这时我们就需要对信息进行判空处理。

在Java 8中,Optional 类提供了一种处理可能为 null 的值的优雅方式。filtermap 方法是 Optional 类中非常有用的两个方法,它们分别用于过滤和转换值。下面是对这两个方法的详细解释和示例。

filter 方法

用途
  • filter 方法用于根据给定的谓词(Predicate)来决定是否保留 Optional 中的值。
  • 如果谓词返回 true,则 Optional 中的值保持不变;如果谓词返回 false,则 Optional 变为 Optional.empty()
方法签名
java 复制代码
Optional<T> filter(Predicate<? super T> predicate)
示例
java 复制代码
Optional<String> optionalValue = Optional.of("1234567890");
Optional<String> filteredValue = optionalValue.filter(s -> s.length() > 5);

System.out.println(filteredValue.orElse("Default Value"));  // 输出: 1234567890

在这个示例中,filter 方法检查字符串的长度是否大于5。因为 "1234567890" 的长度是10,所以 filteredValue 仍然是 Optional.of("1234567890")

map 方法

用途
  • map 方法用于将 Optional 中的值转换为另一种类型。
  • 它接受一个函数(Function),并将该函数应用于 Optional 中的值,生成一个新的 Optional
方法签名
java 复制代码
<U> Optional<U> map(Function<? super T, ? extends U> mapper)
示例
java 复制代码
Optional<String> optionalValue = Optional.of("1234567890");
Optional<Integer> mappedValue = optionalValue.map(s -> s.length());

System.out.println(mappedValue.orElse(0));  // 输出: 10

在这个示例中,map 方法将字符串转换为其长度,生成一个新的 Optional<Integer>

综合示例

结合 filtermap 方法,我们可以更优雅地处理可能为 null 或空字符串的情况,并进行转换。

java 复制代码
dto.setReceiverFixtel(
    Optional.ofNullable(res.getReceiverFixtel())
            .filter(StringUtils::isNotBlank)
            .map(CommonUtil::overlayPhone)
            .orElse("")
);
解释
  1. Optional.ofNullable(res.getReceiverFixtel())

    • 创建一个 Optional 对象,如果 res.getReceiverFixtel() 返回 null,则 OptionalOptional.empty()
  2. .filter(StringUtils::isNotBlank)

    • 使用 filter 方法检查 Optional 中的值是否不是空字符串。如果值是空字符串或 null,则 Optional 变为 Optional.empty()
  3. .map(CommonUtil::overlayPhone)

    • 使用 map 方法将 Optional 中的值转换为电话号码的遮罩形式。CommonUtil::overlayPhone 是一个静态方法,假设它接受一个字符串并返回一个遮罩后的字符串。
  4. .orElse("")

    • 如果 OptionalOptional.empty(),则返回默认值 ""。否则,返回转换后的值。
再举个例子,对值进行判空后类型转换:
java 复制代码
        Optional<String> length = Optional.ofNullable(waybillBaseDto.getLength()).map(String::valueOf);
        Optional<String> width = Optional.ofNullable(waybillBaseDto.getWidth()).map(String::valueOf);
        Optional<String> height = Optional.ofNullable(waybillBaseDto.getHeight()).map(String::valueOf);
相关推荐
zmd-zk4 分钟前
flink学习(2)——wordcount案例
大数据·开发语言·学习·flink
好奇的菜鸟8 分钟前
Go语言中的引用类型:指针与传递机制
开发语言·后端·golang
所待.38312 分钟前
JavaEE之线程初阶(上)
java·java-ee
Winston Wood15 分钟前
Java线程池详解
java·线程池·多线程·性能
Alive~o.017 分钟前
Go语言进阶&依赖管理
开发语言·后端·golang
花海少爷19 分钟前
第十章 JavaScript的应用课后习题
开发语言·javascript·ecmascript
手握风云-20 分钟前
数据结构(Java版)第二期:包装类和泛型
java·开发语言·数据结构
喵叔哟39 分钟前
重构代码中引入外部方法和引入本地扩展的区别
java·开发语言·重构
尘浮生1 小时前
Java项目实战II基于微信小程序的电影院买票选座系统(开发文档+数据库+源码)
java·开发语言·数据库·微信小程序·小程序·maven·intellij-idea
hopetomorrow1 小时前
学习路之PHP--使用GROUP BY 发生错误 SELECT list is not in GROUP BY clause .......... 解决
开发语言·学习·php