近来在优化一些写好的排序,因此会对数据结构考虑得更深刻,为何面试都喜欢面试数据结构,面试对数据结构得熟悉层度,很大的状况下是由于只有数据结构熟悉了,才能用更少时间找到优化时间和空间的方法。面试
估计不少人都有过排序的经验,估计也不少会用到Collections里面的一些数据结构,例如List Set 等等。安全
这一节咱们讨论的是TreeSet。数据结构
TreeSet有什么好处呢?架构
插入的同时就马上进行排序,你只须要设定比如较器,就能按照设定来进行排序,由于他是一个红黑树,树的特征是拥有排序。同时他是个Set,只要比较器认为是同一个,就会被去重。函数
TreeSet使用的结构组件化
其内部是使用了TreeMap,Set值保存在Map的key中,value存了一个Object,Map中若是Key值相同会被认为是同一个,这样就可以实现数据去重。TreeMap内部维护的是一个红黑树。由于是树状结构,那么其查询效率和插入效率都是log(n),固然对应耗时,会由于红黑树平衡调整,会有相应的耗时。性能
TreeSet不是线性安全的,线性安全须要使用ConcurrentSkipListSet。内部是SkipList(跳表)结构实现,在理论上可以在O(log(n))时间内完成查找、插入、删除操做。 优化
####属性变动问题 TreeSet能够指定比较器Comparator,能够经过类中继承Comparable来进行比较迭代。可是里面的属性变化了,不会从新触发排序。须要从新插入排序。例如,TreeSet保存的类文件,类中包含一些列表,列表数据组装而且同时插入到TreeSet,正比如较器须要比较列表中元素的属性,这时候,由于列表是一直在变化的。会出现,类文件插入到TreeSet的时候,再变动类文件中列表的属性,是没法触发TreeSet中自动排序的。TreeSet没法判断到其对象变动状况。3d
你能够采起的策略是cdn
1.插入到TreeSet前须要肯定类文件属性再也不变动。
2.触发变动的时候,从新将其赋值到TreeMap当中,更新比较。
####去重问题 若是比较器中返回为0 ,Set中认为是相等的,会执行去重操做。若是比较器逻辑有问题,可能会触发死循环比较。
####比较器效率问题 TreeSet是边插入边比较,而Collections.sort函数应用场景是List队列当中,二者都能是用比较器来完成操做。
ThreeSet的底层实现是红黑树,它在建立set的过程当中实现排序。Collections.sort是在对整个集合进行排序,按道理来讲使用TreeSet插入集合元素直至创建整个TreeSet过程当中实现排序在时间方面要比Collections.sort对整个集合进行排序效率要高不少,由于它在每次搜索要插入的位置时耗费的时间为log(n),n表明的是当前集合的长度,但实验代表使用Collections.sort对集合进行排序时间耗费要少些。
出现这种状况的缘由是
1.TreeSet的搜索时间为log(n),明显上是比List有优点的。
2.TreeSet在插入的时候须要先建立节点,而List比较并不须要增长额外节点。
3.TreeSet基于红黑树,那么其每次插入都须要检查和维护红黑树平衡,若是失衡会触发红黑树结构调整。
基于2,3两点,无疑会比List更加耗时,数据越多,效率差距越明显。固然这里没有加入List的插入建立节点时间,就算将插入时间加入进来,估计效率上海市Collections.sort占优。