1. Java 容器都有哪些?
- Java 容器分为 Collection 和 Map 两大类,其下又有很多子类,如下所示是Collection和Map的继承体系:
- 具体如下结构:
- Collection
- List
- ArrayList
- LinkedList
- Vector
- Stack
- Set
- HashSet
- LinkedHashSet
- TreeSet
- List
- Map
- HashMap
- LinkedHashMap
- TreeMap
- ConcurrentHashMap
- Hashtable
- HashMap
2. ArrayList和LinkList的区别?
- ArrayList(数组结构):
- 优点:get和set调用花费常数时间,也就是查询的速度快
- 缺点:新项的插入和现有项的删除代价昂贵,也就是添加删除的速度慢
- LinkedList(链表结构):
- 优点:新项的插入和和现有项的删除开销很小,即添加和删除的速度快
- 缺点:对get和set的调用花费昂贵,不适合做查询
- 面试中经常问到一些深入的东西,比如:
- 是否保证线程安全: ArrayList 和 LinkedList 都是不同步的,也就是不保证线程安全;
- 底层数据结构: Arraylist 底层使用的是Object数组;LinkedList 底层使用的是双向循环链表数据结构;
- 插入和删除是否受元素位置的影响: ① ArrayList 采用数组存储,所以插入和删除元素的时间复杂度受元素位置的影响。 比如:执行add(E e)方法的时候, ArrayList 会默认在将指定的元素追加到此列表的末尾,这种情况时间复杂度就是O(1)。但是如果要在指定位置 i 插入和删除元素的话(add(int index, E element))时间复杂度就为 O(n-i)。因为在进行上述操作的时候集合中第 i 和第 i 个元素之后的(n-i)个元素都要执行向后位/向前移一位的操作。 ② LinkedList 采用链表存储,所以插入,删除元素时间复杂度不受元素位置的影响,都是近似 O(1)而数组为近似 O(n)。
- 是否支持快速随机访问: LinkedList 不支持高效的随机元素访问,而ArrayList 实现了RandmoAccess 接口,所以有随机访问功能。快速随机访问就是通过元素的序号快速获取元素对象(对应于get(int index)方法)。
- 内存空间占用: ArrayList的空间浪费主要体现在在list列表的结尾会预留一定的容量空间,而LinkedList的空间花费则体现在它的每一个元素都需要消耗比ArrayList更多的空间(因为要存放直接后继和直接前驱以及数据)。
3. List、Set、Map 之间的区别是什么?
- List、Set、Map 的区别主要体现在两个方面:元素是否有序、是否允许元素重复。
- 三者之间的区别,如下表:
4. HashMap 和 Hashtable 有什么区别?
- 存储:HashMap 运行 key 和 value 为 null,而 Hashtable 不允许。
- 线程安全:Hashtable 是线程安全的,而 HashMap 是非线程安全的。
- 推荐使用:在 Hashtable 的类注释可以看到,Hashtable 是保留类不建议使用,推荐在单线程环境下使用 HashMap 替代,如果需要多线程使用则用 ConcurrentHashMap 替代。
5. Comparable和Comparator区别?
- Comparable接口
- 实现Comparable接口类表示这个类型的对象可以进行比较大小的。 这种可以比较大小的对象可以进行自然排序。
- Comparator接口
- 比较器用于实现对象任意属性进行比较大小。
- 在排序时候可以通过指定属性比较器实现任意属性排序。
- 在排序时候Comparable接口用于进行自然排序,而Comparator接口进行自定义排序,自定义排序更加灵活方便而常用。
- 设计上Comparable不推荐使用,因为对程序本身具有侵入性。
6. 简述HashMap的工作原理?
- HashMap是面向查询优化的数据结构,查询性能优异。
- 在其内部利用数组存储数据。
- 插入数据时,先根据Key的HashCode计算出数组的下标位置,再利用Key的equals()方法检查是否以存在重复的Key,如果不重复直接存储到数组中,如果重复就作为链表存储到散列桶中。
- 插入的数据和数组容量的比值大于加载因子则进行数组扩容,并重新散列,默认的加载因子为“0.75”。
- 查询时,先根据Key的HashCode计算出数组的下标位置,再利用Key的equals()方法检查到Key的位置,如果找到返回Key对应的Value,否则返回Null。
- 由于利用Key的HashCode直接计算出数据的存储位置,由于直接确定数据的存储位置,相对于其他查找方式,查询效率非常高。
7. Iterator 怎么使用?有什么特点?
- Iterator 接口提供遍历任何 Collection 的接口。我们可以从一个 Collection 中使用迭代器方法来获取迭代器实例。迭代器取代了 Java 集合框架中的 Enumeration,迭代器允许调用者在迭代过程中移除元素。
- Iterator 使用代码如下:
List<String> list = new ArrayList<>(); Iterator<String> it = list. iterator(); while(it. hasNext()){ String obj = it. next(); System. out. println(obj); }
- Iterator 的特点是更加安全,因为它可以确保,在当前遍历的集合元素被更改的时候,就会抛出 ConcurrentModificationException 异常。
8. ArrayList 和 Vector 的区别是什么?
- 线程安全:Vector 使用了 Synchronized 来实现线程同步,是线程安全的,而 ArrayList 是非线程安全的。
- 性能:ArrayList 在性能方面要优于 Vector。
- 扩容:ArrayList 和 Vector 都会根据实际的需要动态的调整容量,只不过在 Vector 扩容每次会增加 1 倍,而 ArrayList 只会增加 50%。
9. Collection 和 Collections 有什么区别?
- Collection 是一个集合接口,它提供了对集合对象进行基本操作的通用接口方法,所有集合都是它的子类,比如 List、Set 等。
- Collections 是一个包装类,包含了很多静态方法,不能被实例化,就像一个工具类,比如提供的排序方法: Collections. sort(list)。
10. HashMap 的实现原理?
- HashMap 基于 Hash 算法实现的,我们通过 put(key,value)存储,get(key)来获取。
- 当传入 key 时,HashMap 会根据 key. hashCode() 计算出 hash 值,根据 hash 值将 value 保存在 bucket 里。
- 当计算出的 hash 值相同时,我们称之为 hash 冲突,HashMap 的做法是用链表和红黑树存储相同 hash 值的 value。
- 当 hash 冲突的个数比较少时,使用链表否则使用红黑树。
- HashMap 对应的线程安全类是 ConcurrentHashMap