1. Java 集合框架的基础接口有哪些?
Collection 为集合层级的根接口。一个集合代表一组对象, Java平台不提供这个接口任何直接的实现。
Set 是一个不能包含重复元素的集合。这个接口对数学集合抽象进行建模,被用来代表集合,就如一副牌。
List 是一个有序集合,可以包含重复元素。你可以通过它的索引来访问任何元素。List更像长度动态变换的数组。
Map 是一个将 key 映射到 value 的对象。一个 Map 不能包含重复的 key:每个 key 最多只能映射一个 value。
一些其它的接口有 Queue、Dequeue、SortedSet、SortedMap 和 ListIterator。
2. Iterater 和 ListIterator 之间有什么区别?
a. 我们可以使用 Iterator 来遍历 Set 和 List 集合,而 ListIterator 只能遍历 List。
b. Iterator 只可以向前遍历,而 ListIterator 可以双向遍历。
c. ListIterator 从 Iterator 接口继承,然后添加了一些额外的功能,比如添加一个元素、替换一个元素、获取前面或后面元素的索引位置。
3. 遍历一个 List 有哪些不同的方式?
a. for(String obj : strList){ obj };
b. Iterator<String> it = strList.iterator();
while(it.hasNext()){
String obj = it.next();
}
使用迭代器更加线程安全,因为它可以确保,在当前遍历的集合元素被更改的时候,它会抛出 ConcurrentModificationException.
https://blog.csdn.net/u014519120/article/details/78390400
及时失败:
及时失败也叫快速失败,fast-fail。
”及时失败“的迭代器并不是一种完备的处理机制,而只是”善意地“捕获并发错误,因此只能作为并发问题的预警提示器。它们采用的实现方式是,将计数器的变化与容器关联起来,如果在迭代期间计数器被修改,那么 hasNext 或 next 将抛出 ConcurrentModificationException。 然而,这种检查是在没有同步的情况下进行的,因此可能会看到失效的计数器,而迭代器可能并没有意识到已经发生了修改。这是一种设计上的权衡,从而降低并发修改操作的检测代码对程序性能带来的影响。
4. HashMap 和 HashTable 有何不同?
a. HashMap 允许 key 和 value 为 null, 而 HashTable 不允许。
b. HashTable 是同步的,而 HashMap 不是。所以 HashMap 适合单线程环境, HashTable 适合多线程环境。
c. 在 Java1.4 中引入了 LinkedHashMap, HashMap 的一个子类,假如你想要遍历顺序,你很容易从 HashMap 转向 LinkedHashMap, 但是 HashTable 不是这样的,它的顺序是不可预知的。
d. HashMap 提供对 key 的 Set 进行遍历,因此它是 fail-fast的,但是 HashTable 提供对 key 的 Enumeration 进行遍历,它不支持fail-fast。
e. HashTable 被认为是一个遗留的类,如果你寻求在迭代的时候修改 Map,你应该使用 ConcurrentHashMap。
5. 哪些集合类是线程安全的?
Vector 、 HashTable 、Properties 和 Stack 是同步类,所以它们是线程安全的,可以在多线程环境下使用。java 并发包下一些集合类。
6. Collections 类是什么?
Java.util.Collections 是一个工具类仅包含静态方法,它们操作或返回集合。
7.Comparable 和 Comparator 接口有何区别?
https://www.cnblogs.com/xujian2014/p/5215082.html
Comparable 是排序接口,若一个类实现了 Comparable 接口,重写public int compareTo(T o); 而 Comparator 是比较器,我们若需要控制某个类的次序,可以建立一个”该类的比较器“来进行排序。
Comparable 相当于”内部比较器“,而Comparator 相当于”外部比较器“。
两种方法各有优劣,用 Comparable 简单,只要实现 Comparable 接口的对象直接就成为一个可以比较的对象,但是需要修改源代码。用Comparator 的好处是不需要修改源代码,而是另外实现一个比较器,当某个自定义的对象需要作比较的时候,把比较器和对象一起传递过去就可以比大小了,并且在 Comparator 里面用户可以自己实现复杂的可以通用的逻辑,使其可以匹配一些比较简单的对象,那样就可以节省很多重复劳动了。
高手过招:
1. HashMap 的 put 方法的具体流程?
计算索引、逻辑判断 ——> 扩容 ——> 链表 ——> 红黑树。
2. hashmap 头插尾插问题?
hashmap1.7 版本链表使用的是节点的头插法,扩容时转移链表仍然使用头插法,这样的结果就是扩容后链表会倒置,而hashmap1.8 在插入时使用尾插法,扩容时使用头插法,这样可以保证顺序不变。
3. ConcurrentHashMap 的具体实现知道吗?
https://www.cnblogs.com/everSeeker/p/5601861.html
1.8 中主要做了 2 方面的改进
a. 取消 segment 字段,直接采用 transient volatile HashEntry<K,V> [] table 保存数据,采用table 数组元素作为锁,从而实现了对每一行数据进行加锁,进一步减少并发冲突的概率。
b. 将原先 table 数组 + 单向链表的数据结构,变更为 table 数组 + 单向链表 + 红黑树的结构。
4.TreeMap 的底层实现
红黑树