最近在一个老的java项目中发现使用TreeSet排序后数据变少的生产问题
项目中TreeSet集合排序的步骤如下
- 自定义对象实现Comparable接口,实现compareTo方法
- 通过数据库查询返回一个List(首先排查就是怀疑是不是SQL写错了)
- Set set = new TreeSet();
- set.addAll(List);
问题定位后发现是在实现compareTo方法时当要比较的对象字段有相同值是返回retrurn 0;在实现ArrayList集合排序时返回0不是很正常吗?是的,但是当用TreeSet时就有可能会出现这个诡异的问题。
原理:通过跟踪TreeSet源码发现,TreeSet中使用的TreeMap来存储对象,将TreeSet的元素作为Map的key,继续跟踪TreeMap的put方法源码当比compareTo返回值是0时,key值不会变化(实际是更新key对应的value,TreeSet的value是无意义的),也就是说当出现多个返回0的情况时TreeSet中只会放入第一个元素,后面的全都舍弃掉,源码比较简单,这里就不贴了。
总结:当使用TreeSet排序时,如果实现的compareTo方法中有返回0的情况时就会造成数据丢失。
解决方案:解决方式也很简单,不要让有重复的排序出现就可以了,实际业务如果不能避免那就换一个排序方式
其实原理比较简单,也很容易忽略踩坑。