艾瑞
艾瑞
新闻资讯
中心动态 学习技巧
Java面试题及参考答案-Java基础部分(三)
2019-09-02


1.CorrentHashMap的工作原理

ConcurrenHashMap说是HashMap的升级版

ConcurrentHashMap是线程安全的,但是与Hashtable相比,实现线程安全的方式不同。

Hashtable是通过对hash表结构进行锁定,是阻塞式的,当一个线程占有这个锁时,其他线程必须阻塞等待其释放锁。

ConcurrentHashMap是采用分离锁的方式,它并没有对整个hash表进行锁定,而是局部锁定,也就是说当一个线程占有这个局部锁时,不影响其他线程对hash表其他地方的访问。

ConcurrentHashMap内部有一个Segment<K,V>数组,该Segment对象可以充当锁。Segment对象内部有一个HashEntry<K,V>数组,于是每个Segment可以守护若干个桶(HashEntry),每个桶又有可能是一个HashEntry连接起来的链表,存储发生碰撞的元素。

每个ConcurrentHashMap在默认并发级下会创建包含16个Segment对象的数组,每个数组有若干个桶,当进行put方法时,通过hash方法对key进行计算,得到hash值,找到对应的segment,然后对该segment进行加锁,然后调用segment的put方法进行存储操作,此时其他线程就不能访问当前的segment,但可以访问其他的segment对象,不会发生阻塞等待。

在Java8中,ConcurrentHashMap不再使用Segment分离锁,而是采用一种乐观锁CAS算法来实现同步问题,但其底层还是“数组+链表->红黑树”的实现。

2.Array和ArrayList有什么区别?

Array可以容纳基本类型和对象,而ArrayList只能容纳对象。Array是指定大小的,而ArrayList大小是固定的Array可以包含基本类型和对象类型,ArrayList只能包含对象类型。Array大小是固定的,ArrayList的大小是动态变化的。

3.ArrayList和LinkedList有什么区别?

ArrayList和LinkedList都实现了List接口ArrayList是基于数组实现,它的底层是数组。它可以以O(1)时间复杂度对元素进行随机访问。LinkedList是基于链表实现,每一个元素都和它的前一个和后一个元素链接在一起,在这种情况下,查找某个元素的时间复杂度是O(n)。ArrayList在查找时速度快LinkedList的插入,添加,删除操作速度更快,因为当元素被添加到集合任意位置的时候,不需要像数组那样重新计算大小或者是更新索引。LinkedList比ArrayList更占内存,因为LinkedList为每一个节点存储了两个引用,一个指向前一个元素,一个指向下一个元素。

4.哪些集合类提供对元素的随机访问?

ArrayList、HashMap、TreeMap和HashTable类提供对元素的随机访问。

5.HashSet的底层实现是什么?

HashSet的实现是依赖于HashMap的,HashSet的值都是存储在HashMap中的。

在HashSet的构造法中会初始化一个HashMap对象,HashSet不允许值重复。

因此,HashSet的值是作为HashMap的key存储在HashMap中的,当存储的值已经存在时返回false。

6.Comparable和Comparator接口的区别?

Comparable接口只包含一个compareTo()方法。这个方法可以个给两个对象排序。具体来说,它返回负数,0,正数来表明输入对象小于,等于,大于已经存在的对象。Comparator接口包含compare()和equals()两个方法。compare()方法用来给两个输入参数排序,返回负数,0,正数表明第一个参数是小于,等于,大于第二个参数。

equals()方法需要一个对象作为参数,它用来决定输入参数是否和comparator相等。只有当输入参数也是一个comparator并且输入参数和当前comparator的排序结果是相同的时候,这个方法才返回true。

7.HashSet和TreeSet有什么区别?

HashSet是由一个hash表来实现的,因此,它的元素是无序的。add(),remove(),contains()方法的时间复杂度是O(1)。TreeSet是由一个树形的结构来实现的,它里面的元素是有序的。因此,add(),remove(),contains()方法的时间复杂度是O(logn)。

8. Java中==与equals的区别?

"==" 的作用是判断两个对象的地址是不是相等。即判断两个对象是不是同一个对象。(基本数据类型==比较的是值,引用数据类型==比较的是内存地址)equals() : 它的作用也是判断两个对象是否相等。但它一般有两种使用情况:类没有覆盖equals()方法。则通过equals()比较该类的两个对象时,等价于通过“==”比较这两个对象。类覆盖了equals()方法。一般,我们都覆盖equals()方法来两个对象的内容相等;若它们的内容相等,则返回true(即,认为这两个对象相等)。

9.你重写过 hashcode 和 equals 么,为什么重写equals时必须重写hashCode方法?

hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。如果两个对象相等,则hashcode一定也是相同的如果两个对象相等,对两个对象分别调用equals方法都返回true如果两个对象有相同的hashcode值,它们也不一定是相等的因此,equals方法被覆盖过,则hashCode方法也必须被覆盖

hashCode()的默认行为是对堆上的对象产生独特值。如果没有重写hashCode(),则该class的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)

10.Java的四种引用,强弱软虚,用到的场景

强引用:如果一个对象具有强引用,它就不会被垃圾回收器回收。即使当前内存空间不足,JVM也不会回收它,而是抛出 OutOfMemoryError 错误,使程序异常终止。如果想中断强引用和某个对象之间的关联,可以显式地将引用赋值为null,这样一来的话,JVM在合适的时间就会回收该对象软引用:在使用软引用时,如果内存的空间足够,软引用就能继续被使用,而不会被垃圾回收器回收,只有在内存不足时,软引用才会被垃圾回收器回收。弱引用:具有弱引用的对象拥有的生命周期更短暂。因为当 JVM 进行垃圾回收,一旦发现弱引用对象,无论当前内存空间是否充足,都会将弱引用回收。不过由于垃圾回收器是一个优先级较低的线程,所以并不一定能迅速发现弱引用对象虚引用:顾名思义,就是形同虚设,如果一个对象仅持有虚引用,那么它相当于没有引用,在任何时候都可能被垃圾回收器回收。