- Java类的实例化顺序?
答:父类静态成员和静态代码块 > 子类静态成员和静态代码块 > 父类实例成员和实例代码块 > 父类构造方法 > 子类实例成员和实例代码块 > 子类构造方法
- List< T >和List<?>和有什么区别?
答:List< T >是确定的某一个类型,而List<?>则代表任意类型。 List< T >可以进行读写操作,因为它的类型固定是T类型的,而List<?>则无法做读写操作,是只读类型的。 - 集合类框架的最佳实践有哪些?
答:假如元素的大小是固定的,而且能事先知道,选择用Array而不是ArrayList。一些集合可以指定初始容量,如果我们可以预估元素数目,就可以设置上初始容量来避免hash值的重算和扩容。建议使用泛性,因为它可以在编译时就被检查出错误,避免了运行时报ClassCastException异常,保证了程序的可读性和健壮性。使用JDK提供的不变类来作为Map的key,避免重写hashCode()和 equals()方法。编程的时候接口优于实现。底层的集合实际上是空的情况下,返回长度是0的集合或者是数组,不要返回null。 - 如何让HashMap线程安全?
答:使用Collections.synchronizedMap()方法来获取一个线程安全的集合。如下:
Map<String, String> map = new HashMap<>();
Map synchronizedMap = Collections.synchronizedMap(map);
实现原理其实也是加锁,SynchronizedMap内部搞了个对像锁,名字叫mutex,然后所有的操作都要先去获取这个锁才能执行,保证了线程安全。
-
HashMap 扩充时候是否允许插入?
答:HashMap是线程不安全的,允许扩充的时候插入,不过插入的数据将不存在。 -
队列和栈是什么?
答:队列是一种特殊的线性表,它允许在表的前端(对头)进行删除操作,在表的后端(队尾)进行插入操作。是一种先进先出的线性表。栈是数据结构,按照先进后出的原则来存储数据,先进的元素被压入栈底,最后的元素会在栈顶,从栈顶开始弹出数据,所以最后一个进去栈的元素反而会最先出来。 -
在Queue中的poll()和remove()有什么区别?
答:两者都会返回Queue中的第一个元素,同时删除Queue中的这个元素,只是如果Queue中没有元素的话,使用poll()会返回null,而remove()会直接抛异常。 -
Java中的另一个线程安全的与HashMap极其类似的类是什么,在哪个包下?
答:ConcurrentHashMap类。在java.util.concurrent(JUC)包下。 -
同样是线程安全,ConcurrentHashMap与HashTable在线程同步上有什么不同?
答:HashTable是使用synchronized关键字来进行加锁的,锁粒度太大,性能不高。而ConcurrentHashMap在JDK1.7采用分段锁的方式来控制并发,减小了锁粒度,但是ConcurrentHashMap在JDK1.8后,又采用了CAS(无锁算法)加上synchronized关键字的方法。 -
ConcurrentHashMap的数据结构在JDK1.7和JDK1.8中有什么变化,为什么这样做?
答:在JDK1.7中,ConcurrentHashMap底层的数据结构采用的是数组+链表,但是这样会有一个问题,如果好多数据的hash值都相同,那相对于这个hash值下的链表就会拉的很长,检索数据的效率就会变成O(n)。所以JDK1.8后引入了红黑树,底层数据结构变成了数组+链表+红黑树,只要链表下的元素数据大于等于8,结构就会由链表转成红黑树,时间复杂度也就由O(n)转为了O(logn),效率得到了提升。