概述
别人遇到的bug,收集起来以防自己同样犯错。
bug产生的场景:
项目中对文章的详情内容通过Redis做了缓存,详情中以List形式关联了一些其他内容。在Redis中存储数据也将会是从业务中获取的List集合。存储数据要求3条即可,但是查询接口返回的数据不一定为3条,当多于3条是,就需要截取,在截取的过程中使用了list.subList(0,3),来获取其中3条数据。之后就报错了。。。 (由于这块业务的负责人是另一位同事,自己没有看到异常信息,无法截图,故遇到时能够想起即可)
原错误代码:
分析:
切割后的存储形式应该就变成了java.util.ArrayList$SubList,这种格式的对象从Redis中拿出来是没法进行反序列化的。原因是list接口并没有实现序列化。在jdk6中,ListsubList(int fromIndex, int toIndex)返回的是没有实现Serializable接口的java.util.RandomAccessSubList。在其父类或者接口中都找不到Serializable这个标志。而在jdk7和8中,sublist实现,它是在ArrayList中直接搞了一个私有内部类:private class SubList extends AbstractListimplements RandomAccess,而jdk6中class RandomAccessSubListextends SubListimplements RandomAccess,注意这里的SubList跟上面的是不同的,这里的SubList是AbstractList的内部类。
综上,ArrayList.subList方法返回的对象是一个sublist类型的视图,这个sublist类型的是ArrayList的一个内部类,不支持序列化。视图的含义就是它里面的元素数量变了,但是操作其中的元素实际上还是操作的原来的list,并不是新的那份list。如果改变原有的list,那么就会抛出ConcurrentModificationException异常。即:
就算未对原有list进行修改,但是因其未做序列化,从Redis中读取数据时会因无法反序列化而出现问题。
解决方案:
1.重新创建一个可以实现序列化的list集合,将截取后的list存入,实现序列化
List list = new ArrayList(imgList.subList(0,3));
jsonRelatedArticles.setImgList(list);
or
ListserializedList= new ArrayList();
serializedList.addAll(sublist);
//在这里就是,其实跟上边一种大同小异
ListserializedList= new ArrayList<>();
serializedList.addAll(imgList.subList(0,3));
jsonRelatedArticles.setImgList(serializedList);
2.避免使用subList,使用循环遍历一个个add。
if (a.getImgList() != null && a.getImgList().size() >= 3){
ListimgList = new ArrayList<>(3);
for (int i = 0; i < 3; i++){
JsonArticleDetail.JsonImg jsonImg = new JsonArticleDetail.JsonImg();
jsonImg.setUrl(imageUtil.getCommonImageUrl(a.getImgList().get(i).getImgPath()));
imgList.add(jsonImg);
}
}
//注意a.getImgList().get(i).getImgPath()可能会有空指针异常,本代码只简要表明重点,视情况判断。
3.其实单针对于本次错误代码而言,只需要在原有循环上简单修改即可。如下:
综上:
发现简单一个subList就有很大的陷阱,所以基础知识还是需要牢固。
附:java.util.List.subList使用注意
redis数据存储形式:
ridis大方面来说,就是一个K-V数据库,用于存储数据,这个数据库也可以存储复杂结构的数据,像有关的集合数据,所以它也具备了对复杂数据的高效查询,(故障恢复特性,文件有关数据持久化能力)
数据跨平台存储通过网络的传输层进行传输,所以必须序列化
最后
以上就是开心舞蹈为你收集整理的java list存储错乱,【bug】 -- List.subList()未序列化导致Redis报错的全部内容,希望文章能够帮你解决java list存储错乱,【bug】 -- List.subList()未序列化导致Redis报错所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复