在stream中 toList() 和 collect(Collectors.toList()) 进行redis序列化存储的不同!!(当使用 spring-Cache的@Cacheable的时候)

在stream中 toList() 和 collect(Collectors.toList()) 进行redis存储序列化的不同!!(当使用 spring-Cache的@Cacheable的时候)

在大多数情况下,这两者其实并没有区别, 并且, toList() 还可以看成是 collect(Collectors.toList()) 语法糖:

chatGPT3.5的回答:
collect(Collectors.toList())是将流中的元素收集到一个新的列表中,而toList()是在Java
16中引入的便捷方法,具有相同的功能。toList()方法更加简洁并且易于阅读,是Java编程语言的语法糖,让代码更加简洁易懂。

  但是当进行使用spring-cache框架的 @cacheable 注解将数据存储到 redis 中 进行 序列化存储的时候,它们两者的不同就体现出来了. 使用 toList() 进行存储的数据, 在前端第二次要读取数据的时候,会报错:

Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.data.redis.serializer.SerializationException: Could not read JSON: Unexpected token (START_OBJECT), expected VALUE_STRING: need JSON String, Number of Boolean that contains type id (for subtype of java.lang.Object)

而使用 collect(Collectors.toList()) 进行redis缓存的数据,在前端第二次读取的时候不报错.

  二者在 @cacheable 注解下进行redis序列化存储时候,collect(Collectors.toList()) 会在进行序列化存储的时候在数据的开头添加一行数据 : “java.util.ArrayList”,toList() 不会. (通过在线JSON文件比对工具,其他没有不同).
猜测是 @cacheable注解会依据这行数据,进行正确的序列化取出,而由于 toList() 没有这行数据,导致不能正确的序列化取出,导致报错.

chatGPT4.0的回答:
  首先,toList()和 collect(Collectors.toList())这两种方式都是将流中的元素收集到一个列表中。在Java 16中,“toList()”是一个直接在 Stream 上的方法,它返回一个固定大小,不可修改的结果集。这个结果集在某些情况下可能是更有效率的选择。
  然而,从您的报错信息来看,这个错误是由Jackson在反序列化JSON数据时发生问题所引起的。Jackson期望具有某种类型标识符的值(如一个字符串、数字或布尔值),而在JSON数据中遇到的却是一个对象的开始标识。
  问题的更深层原因在于toList()返回的是一个不可变的列表,而collect(Collectors.toList())返回的是一个ArrayList。在Java中,ArrayList和其他常见的集合类型(如LinkedList)都实现了java.util.List接口,但具体的实现细节都各有不同。这种差异可能影响Jackson的序列化/反序列化过程,使其无法正确处理由toList()返回的不可变列表。
  因此,虽然在许多情况下,toList()是collect(Collectors.toList())的语法糖,但因为它们返回不同类型的列表,所以在某些特定的情况(如与Jackson结合使用)下,可能会导致不同的行为。所以在使用toList()时会产生此类错误。推荐在处理Redis数据时还是使用collect(Collectors.toList())。

  GPT的回答第二段,验证了这一点.在 @cacheable 注解下, 使用 collect(Collectors.toList()) 会添加一个标识符, 而 toList() 不会添加标识符.

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值