HashMap概述:HashMap是基于哈希表的Map接口的非同步实现,以键值对的存储形式存在,且线程 不安全。此实现提供所有可选的映射操作,并允许使用空键值对,但并不保证映射的顺序,尤其是顺序 恒定性。
HashMap数据结构:在java中,最基本的数据结构就是两种,一个是数组,另一个是模拟指针(引 用),所有的数据结构都可以用这两个基本结构来构造,HashMap也是。另外HashMap实际上是一 个”链表散列+红黑树“的数据结构,即数组、链表和红黑树的结合体。
(1)HashMap线程不安全主要体现在哪 多线程环境下,使用put方法会发生数据覆盖的情况。 (2)HashMap底层数据结构 数组+链表 数组+链表+红黑树 在JDK1.8后,当链表长度超过8时,就会转换为红黑树,当小于6时变回链表。 在负载因子默认为0.75时,单个hash槽内元素个数为8的概率小于百万分之一(特别特别小),所以将 7作为分水岭,当等于7的时候不转换,大于等于8的时候转换为红黑树。
(3)哈希扩容 扩容阈值:负载因子(0.75)*当前容量 扩容步骤:1.创建一个新的数组,长度为原来的两倍 2.遍历取出原数组的所有内容,重新进行哈希函数计算出新的哈希值 3.重新插入元素
(4)HashMap为什么是两倍扩容 哈希值的计算是通过除留余数法获取,因为哈希表的大小始终为2的n次幂,所以可以将取模运算转为位 运算,效率更高。而且移动的数据也只有大约一半。
HashSet底层由HashMap实现,他的值存放于HashMap的键上,并使得HashMap的值统一为 PRESENT。HashSet的实现比较简单,相关HashSet的操作基本都是直接调用底层HashMap的相关方 法来完成,HashSet不允许重复值。
ArrayList底层使用动态数组实现,实现了 RandmoAccess 、 Cloneable 、 Serializable 接口,因此可 以实现随机访问、克隆、序列化等功能。因此他的查找和访问效率更高,但新增和删除效率较低。 调用他的构造函数时只会出初始化数组的大小,而size这个变量不会初始化,此时调用set方法指定下标 设置数据会抛出数组越界异常,因此set方法中是根据size来判断是否可以设置当前下标的数据。
LinkedList底层使用双向链表实现,因此他的新增和删除效率更高,但查找和访问效率较低。实现了队 列接口,具有先进先出的功能。内部维护了链表长度以及头尾节点,获取长度不需要遍历。 (1)ArrayList与LinkedList的区别是什么 前者基于动态数组实现,方便查找和访问;后者基于双向链表实现,方便添加和删除。
(2)如何实现数组与List之间的转换 数组转List:使用Arrays.asList(array)进行转换。 List转数组:使用List自带的toArray()方法进行转换。
(3)Array与ArrayList的区别是什么
1. Array是数组,而ArrayList是继承与List集合的列表,是对数组的加强。
2. Array可以存储基本类型和对象,而ArrayList只能存储对象。
3. Array是指定固定大小的,而ArrayList大小是可以自动扩展的。
4. Array的内置方法没有ArrayList多,比如addAll、removeAll、iteration 等方法只有ArrayList有 。
Vector的内部实现类似于ArrayList,但是他的很多方法都加入了同步语句,因此是线程安全(相对安 全)的,实现了List、RandomAccess、Cloneable、 Serializable等接口 。
(1)说一下Vector与ArrayList的区别
1. Vector使用了Synchronized来实现线程同步,是线程安全的;ArrayList是非线程安全的。
2. ArrayList的性能优于Vector
3. ArrayList和Vector都会根据实际需求进行扩容,只不过Vector扩容每次会增加一倍,而ArrayList 扩容只会增加50%
poll()和remove()都是从队列中取出一个元素,但是前者在获取元素失败的时候会返回空,但是后者失 败的时候会抛出异常。
1. Vector:比ArrayList多出了一个同步化机制(线程安全),但是因为效率低,不太建议使用了。 2. HashTable:就比HashMap多了个线程安全,去除了contains方法,增加了containsKay和 containsVal方法,且不允许出现空键值对。
3. statck:堆栈类,先进后出。
4. enumeration:枚举,相当于迭代器。
迭代器是一种设计模式,是一个对象,不是一个集合,而是一种用于访问集合的方法。它可以遍历并选 择序列(ArrayList、HashSet)中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常被称 为”轻量级“对象,因为创建它的代价小。