0%

面试题-Java-Collecions-Framework

本章属于持续学习、长期更修。

对比下Vector、ArrayList、LinkedList之前有何区别。

Vector

  • Vector是Java早期提供的线程安全动态数组,和ArrayList之间在扩容方面有很多的区别,Vector是扩容2倍,而ArrayList扩容1.5倍。

ArrayList

  • ArrayList平时开发过程中使用最多的,是一个线程不安全的动态数组。所以性能上相对Vector好很多。

LinkedList

  • 它是一个链表,对比ArrayList和Vector不需要扩容。但没有实现RandomAccess 接口。RandomAccess的实现,则尽量用for(int i = 0; i < size; i++) 来遍历而不要用Iterator迭代器来遍历。

ArrayList和linkedList的区别

  • Array (数组)是基于索引(index)的数据结构,它使用索引在数组中搜索和读取数据是很快的。

  • Array获取数据的时间复杂度是O(1),但是要删除数据却是开销很大,因为这需要重排数组中的所有数据, (因为删除数据以后, 需要把后面所有的数据前移)

1
2
3
// 数组初始化必须指定初始化的长度, 否则报错
int[] a = new int[4];//推介使用int[] 这种方式初始化
int c[] = {23,43,56,78};//长度:4,索引范围:[0,3]
  • List—**是一个有序的集合,可以包含重复的元素,提供了按索引访问的方式,它继承Collection。List有两个重要的实现类:

  • ArrayList: 可以看作是能够自动增长容量的数组

  • ArrayList的toArray方法返回一个数组。

  • ArrayList**的asList方法返回一个列表。

HashMap加载因子为什么是 0.75?

  • 加载因子也叫扩容因子或负载因子,用来判断什么时候进行扩容的,假如加载因子是 0.5,HashMap 的初始化容量是 16,那么当 HashMap 中有 16*0.5=8 个元素时,HashMap 就会进行扩容。

  • 那加载因子为什么是 0.75 而不是 0.5 或者 1.0 呢?

    • 这其实是出于容量和性能之间平衡的结果:

    • 当加载因子设置比较大的时候,扩容的门槛就被提高了,扩容发生的频率比较低,占用的空间会比较小,但此时发生 Hash 冲突的几率就会提升,因此需要更复杂的数据结构来存储元素,这样对元素的操作时间就会增加,运行效率也会因此降低;

    • 而当加载因子值比较小的时候,扩容的门槛会比较低,因此会占用更多的空间,此时元素的存储就比较稀疏,发生哈希冲突的可能性就比较小,因此操作性能会比较高。

  • 所以综合了以上情况就取了一个 0.5 到 1.0 的平均数 0.75 作为加载因子。

当有哈希冲突时,HashMap 是如何查找并确认元素的?

  • 当哈希冲突时我们需要通过判断 key 值是否相等,才确认此元素是不是我们想要的元素。

HashMap 源码中有哪些重要的方法?

  • putVal()新增
  • resize()扩容
  • get()查询

HashMap和HashTable的区别?

  • 两者父类不同

    • HashMap是继承自AbstractMap类,而Hashtable是继承自Dictionary类。不过它们都实现了同时实现了map、Cloneable(可复制)、Serializable(可序列化)这三个接口。
  • 对外提供的接口不同

    • Hashtable比HashMap多提供了elments() 和contains() 两个方法。elments() 方法继承自Hashtable的父类Dictionnary。elements() 方法用于返回此Hashtable中的value的枚举。contains()方法判断该Hashtable是否包含传入的value。它的作用与containsValue()一致。事实上,contansValue() 就只是调用了一下contains() 方法。
  • null支持不同

    • Hashtable:key和value都不能为null。

    • HashMap:key可以为null,但是这样的key只能有一个,因为必须保证key的唯一性;可以有多个key

      值对应的value为null。

  • 线程安全不同

    • HashMap是线程不安全的,在多线程并发的环境下,可能会产生死锁等问题,因此需要开发人员自己处理多线程的安全问题。

    • Hashtable是线程安全的,它的每个方法上都有synchronized 关键字,因此可直接用于多线程中。

    • 虽然HashMap是线程不安全的,但是它的效率远远高于Hashtable,这样设计是合理的,因为大部分的使用场景都是单线程。当需要多线程操作的时候可以使用线程安全的ConcurrentHashMap。