# 在stream中 toList() 和 collect(Collectors.toList()) 進(jìn)行redis存儲(chǔ)序列化的不同!!(當(dāng)使用 spring-Cache的@Cacheable的時(shí)候)
? 在大多數(shù)情況下,這兩者其實(shí)并沒(méi)有區(qū)別, 并且, **toList()** 還可以看成是 **collect(Collectors.toList())** 語(yǔ)法糖:
>? chatGPT3.5的回答:
> collect(Collectors.toList())是將流中的元素收集到一個(gè)新的列表中,而toList()是在Java
> 16中引入的便捷方法,具有相同的功能。toList()方法更加簡(jiǎn)潔并且易于閱讀,是Java編程語(yǔ)言的語(yǔ)法糖,讓代碼更加簡(jiǎn)潔易懂。
  但是當(dāng)進(jìn)行使用**spring-cache**框架的 **@cacheable** 注解將數(shù)據(jù)存儲(chǔ)到 **redis** 中 進(jìn)行 序列化存儲(chǔ)的時(shí)候,它們兩者的不同就體現(xiàn)出來(lái)了. 使用 ***toList()*** 進(jìn)行存儲(chǔ)的數(shù)據(jù), 在前端第二次要讀取數(shù)據(jù)的時(shí)候,會(huì)報(bào)錯(cuò):
> 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())*** 進(jìn)行redis緩存的數(shù)據(jù),在前端第二次讀取的時(shí)候不報(bào)錯(cuò).
  二者在 **@cacheable** 注解下進(jìn)行redis序列化存儲(chǔ)時(shí)候,**collect(Collectors.toList())** 會(huì)在進(jìn)行序列化存儲(chǔ)的時(shí)候在數(shù)據(jù)的開(kāi)頭添加一行數(shù)據(jù) :? **"java.util.ArrayList",**? 而 **toList()** 不會(huì). (通過(guò)在線JSON文件比對(duì)工具,其他沒(méi)有不同).
猜測(cè)是 **@cacheable**注解會(huì)依據(jù)這行數(shù)據(jù),進(jìn)行正確的序列化取出,而由于 **toList()** 沒(méi)有這行數(shù)據(jù),導(dǎo)致不能正確的序列化取出,導(dǎo)致報(bào)錯(cuò).
> chatGPT4.0的回答:
>   首先,toList()和 collect(Collectors.toList())這兩種方式都是將流中的元素收集到一個(gè)列表中。在Java 16中,“toList()”是一個(gè)直接在 Stream 上的方法,它返回一個(gè)固定大小,不可修改的結(jié)果集。這個(gè)結(jié)果集在某些情況下可能是更有效率的選擇。
>  然而,從您的報(bào)錯(cuò)信息來(lái)看,這個(gè)錯(cuò)誤是由Jackson在反序列化JSON數(shù)據(jù)時(shí)發(fā)生問(wèn)題所引起的。Jackson期望具有某種類型標(biāo)識(shí)符的值(如一個(gè)字符串、數(shù)字或布爾值),而在JSON數(shù)據(jù)中遇到的卻是一個(gè)對(duì)象的開(kāi)始標(biāo)識(shí)。
>  問(wèn)題的更深層原因在于toList()返回的是一個(gè)不可變的列表,而collect(Collectors.toList())返回的是一個(gè)ArrayList。在Java中,ArrayList和其他常見(jiàn)的集合類型(如LinkedList)都實(shí)現(xiàn)了java.util.List接口,但具體的實(shí)現(xiàn)細(xì)節(jié)都各有不同。這種差異可能影響Jackson的序列化/反序列化過(guò)程,使其無(wú)法正確處理由toList()返回的不可變列表。
? >  因此,雖然在許多情況下,toList()是collect(Collectors.toList())的語(yǔ)法糖,但因?yàn)樗鼈兎祷夭煌愋偷牧斜?,所以在某些特定的情況(如與Jackson結(jié)合使用)下,可能會(huì)導(dǎo)致不同的行為。所以在使用toList()時(shí)會(huì)產(chǎn)生此類錯(cuò)誤。推薦在處理Redis數(shù)據(jù)時(shí)還是使用collect(Collectors.toList())。
  GPT的回答第二段,驗(yàn)證了這一點(diǎn).在 **@cacheable** 注解下, 使用 **collect(Collectors.toList())** 會(huì)添加一個(gè)標(biāo)識(shí)符, 而 **toList()** 不會(huì)添加標(biāo)識(shí)符.