集合数据结构详解
链表
LinkedList
Java 程序中所有的链表实际上都是双向链接的 – 即每个节点还存放着指向前驱节点的引用,链表不支持随机访问元素的方法,但是 LinkedList 提供了一个 get 方法,get 方法做了优化,如果索引的大于 size()/ 2 那么它就会从尾部开始检索数据。
ListIterator 类可以从前后两个方向遍历链表中的元素。
ArrayList 和 linkedLIst 在用法上没有什么区别,但是在功能上是有区别的,linkedList 经常用在增删操作比较多而查询操作很少的情况下,ArrayList 则相反
Vector
Vector 类的所有方法都是同步的,可以由两个线程安全方法一个 Vector 对象,但是在由一个线程访问是会耗费大量的时间在处理同步操作上,建议在不需要同步的情况下使用 ArrayList。
散列集
散列集可以快速的查找所需要的对象,它为每个对象计算一个整数,称为散列码。如果是自定义对象,就需要自己负责这个类的 hashCode 方法。
散列表用链表数组实现,每个列表被称为桶,如果要保存数据,需要先计算它的散列码例如:某个对象的散列码是 76268,并且这个集合拥有 128 个桶,该对象保存在 108 号桶中(76268%128 余 108),这个时候会有两种情况,这个桶中没有其他元素,那么就会将数据插入这个链表的头部,还有一种情况就是这个桶被占满,这也是不可避免的,称为散列冲突,这种情况链表会从新扩容(原来个数的 2 次幂)并且将旧数据添加到新链表中,废弃旧链表,
桶也一样,有默认的装填因子(0.75 默认值),如果列表中超过 75% 的位置已经填入了元素,那么散列就会在散列,个数是原来的两倍,将旧数据添加到新列表中废弃原来的列表。
Set 集合没有重复元素,在使用 add 方法添加会先查找列表中是否存在当前对象,如果没有才会添加,hashSet 实现了散列表集。
树集
TreeSet 类与散列集很类型,它是一个有序的集合,如果将元素添加到集合中,它会自动排序,它的排序是树结构完成构建(当前使用的是红黑树),将一个元素添加到树种要比添加到散列中要慢很多,原因是如果树中包含了 1000 个元素,查找新元素的位置大约需要比较 10 次,而散列只需要计算 hashCode,添加到桶中。
TreeSet 是怎么保证元素循序的,使用的是 comparable 接口进行比较。
优先级队列
PriortyQueue();
元素可以按照任意循序插入,总是按照排序的循序进行检索,无论何时调用 remode 方法,总会获得当前队列优先级最低的元素,优先级使用一个高效的数据结构,称为堆,它是一个可以自我调整的二叉树,对树执行添加或删除可以让最小的元素移动的根部,而不必对元素进行排序,使用队列的典型就是任务调度,每当启动一个新的任务是,都将优先级最高的元素从队列中剔除,一般程序的默认优先级 1 是最大。
映射表
是键 / 值对映射表,java 中提供了两个通用的实现 HashMap 和 treeMap。
HashMap:是散列映射键值对集合,无序的。
TreeSet : 是树映射,是有序的。
通常来说 HashMap 比 TreeSet 添加删除要快,如果不需要排序选择散列好
专用集和映射表类 1. 弱散列映射表
WeakJHashMap 的出现是为了解决一个有趣的问题,如果一个值已经不再使用了,那么垃圾回收器为什么不回收他呢!遗憾的是垃圾回收器跟踪的是活跃的对象,只要映射表是活动的,那么它的桶也是活动的,垃圾回收器是无法回收的。
WeakHashMap 使用了弱引用保存键,WeakReference 对象会将引用保存到另一个对象中,垃圾回收器用一种特有的方法处理。
只要这个引用没有人使用了,垃圾回收器就会回收它,但是要将这个弱引用放入队列中,WeakHashMap 会定期检查队列,一个弱引用进入队列就代表它已经没有人使用了。
2.链接散列集和链接映射表**
Jdk1.4 新增了两个类:linkedHashSert 和 linkedHashMap,用来记录插入元素的顺序,链接散列映射表将用访问序列,而不是插入的顺序,每当调用 get 或 put 都会删除原来的位置,并且将元素放到链表的尾部, 这个操作只会元素在链表中的位置,不会影响散列中的桶,有一个好处是可以将访问频率高的元素放到内存中,而反问频率第的从数据库访问,linkedHashMap 有个一子类覆盖他的 removeEldestEntry()可以实现。
3.枚举集与映射表**
用的少不做研究
4.标识散列映射表**
Jdk1.4 还增加了一个特殊的类:IdentityHashMap, 在这个类中键的散列值不是使用 HashCode 计算的,而是使用 System.identityHashCode 计算,这是 Object。HashCode 方法根据对象的内存地址来计算,在对两个对象进行比较的时候用的是 == 而不是 equals,可以用来跟中每个对象的遍历状况。