1、HashSet如何按插入顺序排序
可以使用LinkedHashSet,它是继承HashSet来实现,需要注意的是,LinkedHashSet也是线程不安全,如下为部分源码图:
2、HashSet如何按自然顺序排序
可以使用TreeSet,它是通过TreeMap来实现,TreeMap默认按key自然顺序,可以通过comparator比较器实现自定义顺序,如下为部分源码图:
3、HashSet底层实现原理
HashSet底层基于HashMap来实现,相关的数据操作基本都是调用HashMap的方法来实现,此外,HashSet不允许有重复值。
4、TreeSet底层数据结构
TreeSet底层是基于TreeMap实现,因此它的数据结构是:红黑树。
5、Java为什么不推荐使用{{}}来初始化集合
List<String> list = new ArrayList<>() {{
add("aaa");
add("bbb");
}}
Java不推荐使用类似上面双括号({{}})的方式初始化集合,原因是双括号初始化会产生匿名内部类,而非静态匿名内部类又会隐式强引用外部类,如果两个类的实例对象的生命周期不一致,就会导致外部类无法被及时回收,如果同时产生大量匿名内部类,就有可能造成内存泄露。
替代方案:
List<String> list = Stream.of("aaa", "bbb").collect(Collectors.toList())
Map map = Map.of("key1", "val1", "key2", "val2")
6、简述阻塞队列
含义:阻塞队列(BlockingQueue)是一个支持两个附加操作的队列,分别是支持阻塞插入和阻塞删除。
1)支持阻塞插入:当队列满时,会阻塞插入元素的线程,直到队列有空位允许插入元素为止。
2)支持阻塞删除:当队列空时,会阻塞获取元素的线程,直到队列有元素允许获取数据为止。
下图为阻塞队列相关方法
7、阻塞队列是线程安全吗
阻塞队列是线程安全,阻塞队列中的关键方法都使用了内部锁或其他形式的并发控制,因此,对阻塞队列的写入、读取等操作无需考虑并发问题。如下为部分源码图:
8、阻塞队列常用的应用场景
阻塞队列常用于生产者和消费者场景。
1)生产者:生产者线程负责往队列里添加元素。
2)消费者:消费者线程负责从队列中读取数据。
Java自带的线程池就使用了阻塞队列,如下图:
9、列举几个Java阻塞队列
1)ArrayBlockingQueue:底层由数组组成的有界阻塞队列。
2)LinkedBlockingQueue:底层由链表组成的有界阻塞队列。
3)PriorityBlockingQueue:支持优先级排序的无界阻塞队列。
4)DelayQueue:优先级无界阻塞队列。
5)SynchronousQueue:不存储元素的阻塞队列。
6)LinkedTransferQueue:底层由链表组成的无界阻塞队列。
7)LinkedBlockingDeque:底层由链表组成的双向阻塞队列。
本篇集合面试题到此完毕,下一篇开始收录多线程面试题。