java基础面试题(二十一)

  1. Java类的实例化顺序?
    答:父类静态成员和静态代码块 > 子类静态成员和静态代码块 > 父类实例成员和实例代码块 > 父类构造方法 > 子类实例成员和实例代码块 > 子类构造方法
  2. List< T >和List<?>和有什么区别?
    答:List< T >是确定的某一个类型,而List<?>则代表任意类型。 List< T >可以进行读写操作,因为它的类型固定是T类型的,而List<?>则无法做读写操作,是只读类型的。
  3. 集合类框架的最佳实践有哪些?
    答:假如元素的大小是固定的,而且能事先知道,选择用Array而不是ArrayList。一些集合可以指定初始容量,如果我们可以预估元素数目,就可以设置上初始容量来避免hash值的重算和扩容。建议使用泛性,因为它可以在编译时就被检查出错误,避免了运行时报ClassCastException异常,保证了程序的可读性和健壮性。使用JDK提供的不变类来作为Map的key,避免重写hashCode()和 equals()方法。编程的时候接口优于实现。底层的集合实际上是空的情况下,返回长度是0的集合或者是数组,不要返回null。
  4. 如何让HashMap线程安全?
    答:使用Collections.synchronizedMap()方法来获取一个线程安全的集合。如下:
    Map<String, String> map = new HashMap<>();
    Map synchronizedMap = Collections.synchronizedMap(map);

实现原理其实也是加锁,SynchronizedMap内部搞了个对像锁,名字叫mutex,然后所有的操作都要先去获取这个锁才能执行,保证了线程安全。

  1. HashMap 扩充时候是否允许插入?
    答:HashMap是线程不安全的,允许扩充的时候插入,不过插入的数据将不存在。

  2. 队列和栈是什么?
    答:队列是一种特殊的线性表,它允许在表的前端(对头)进行删除操作,在表的后端(队尾)进行插入操作。是一种先进先出的线性表。栈是数据结构,按照先进后出的原则来存储数据,先进的元素被压入栈底,最后的元素会在栈顶,从栈顶开始弹出数据,所以最后一个进去栈的元素反而会最先出来。

  3. 在Queue中的poll()和remove()有什么区别?
    答:两者都会返回Queue中的第一个元素,同时删除Queue中的这个元素,只是如果Queue中没有元素的话,使用poll()会返回null,而remove()会直接抛异常。

  4. Java中的另一个线程安全的与HashMap极其类似的类是什么,在哪个包下?
    答:ConcurrentHashMap类。在java.util.concurrent(JUC)包下。

  5. 同样是线程安全,ConcurrentHashMap与HashTable在线程同步上有什么不同?
    答:HashTable是使用synchronized关键字来进行加锁的,锁粒度太大,性能不高。而ConcurrentHashMap在JDK1.7采用分段锁的方式来控制并发,减小了锁粒度,但是ConcurrentHashMap在JDK1.8后,又采用了CAS(无锁算法)加上synchronized关键字的方法。

  6. ConcurrentHashMap的数据结构在JDK1.7和JDK1.8中有什么变化,为什么这样做?
    答:在JDK1.7中,ConcurrentHashMap底层的数据结构采用的是数组+链表,但是这样会有一个问题,如果好多数据的hash值都相同,那相对于这个hash值下的链表就会拉的很长,检索数据的效率就会变成O(n)。所以JDK1.8后引入了红黑树,底层数据结构变成了数组+链表+红黑树,只要链表下的元素数据大于等于8,结构就会由链表转成红黑树,时间复杂度也就由O(n)转为了O(logn),效率得到了提升。

发布了178 篇原创文章 · 获赞 180 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/weixin_38106322/article/details/104325046