Java 通用容器类和总结(三):容器类总结

  1. Java 中容器总结?
    答:

    • Collection: 根接口,表示单个元素的集合,有基本的增、删、查、遍历等方法,但没有定义元素见的顺序或位置,也没有规定是否有重复元素。

      • List: 是 Collection 的子接口,表示有位置或顺序的数据集合,增加了根据索引位置进行操作的方法

        • ArrayList: 基于数组实现,随机访问效率很高,但从中间插入和删除元素需要移动元素,效率比较低。
        • LinkedList: 基于链表实现,与 ArrayList 特点相反,随机访问效率比较低,但增删元素只需要调整临近节点的链接,效率比较高。
      • Set: 是 Collection 的子接口,没有增加新的方法,但保证不含重复元素。

        • HashSet: 基于哈希表实现,要求键重写 hashCode() 方法,效率很高,但元素间没有顺序。

          • LinkedHashSet: 可以按插入有序。
        • TreeSet: 基于排序二叉树实现,元素按比较有序,元素需要实现 Comparable 接口,或者创建 TreeSet 时提供一个 Comparator 对象。

        • EnumSet: 针对枚举类型,基于位向量实现,效率很高。

      • Queue: 是 Collection 的子接口,表示先进先出的队列,在尾部添加,在头部查看或删除。

        • Deque: 是 Queue 的子接口,表示更为通用的双端队列,有明确的在头或尾进行查看、添加和删除的方法。

          • ArrayDeque: 普通队列的实现类,基于循环数组实现。

          • 普通队列有两个主要的实现类:LinkedListArrayDequeLinkedList 基于链表实现,ArrayDeque 基于循环数组实现。一般而言,如果只需要 Deque 接口,ArrayDeque 的效率更高一些。

        • PriorityQueue: 是一个特殊的 Queue 的实现类,表示优先级队列,内部是用堆实现的。堆除了可以用于实现优先级队列,还可以高效方便地解决很多其他问题,比如,求前 K 个最大的元素、求中值等。
    • Map: 根接口,表示键值对的集合,经常根据键进行操作。

      • HashMap: 基于哈希表实现,要求键重写 hashCode() 方法,操作效率很高,但元素没有顺序。

        • LinkedHashMap: 按插入或访问有序。之所以能有序,是因为每个元素还加入到了一个双向链表中。如果键本来就是有序的,使用 LinkedHashMap 而非 Treemap 可以提高效率。按访问有序的特点是可以方便地用于实现 LRU 缓存。
      • TreeMap: 基于红黑树(大致平衡的排序二叉树)实现,要求键实现 Comparable 接口,或提供一个 Comparator 对象,操作效率稍低,但可以按键有序。

      • EnumMap: 是 Map 的一个专门的实现类,键为枚举类型,内部使用效率更高的两个数组实现。

  2. Java 中容器类的线程安全性?
    答:

    • 除了 HashtableVectorStack,其他容器类都是线程不安全的,即:如果多个线程同时读写同一个容器对象,是不安全的。
    • 如果需要线程安全,可以使用 Collection 提供的 synchronizedXXX() 方法对容器对象进行同步,或者使用专门的线程安全的容器类
  3. 容器类中的迭代器的特点是?
    答:都会在迭代过程中进行结构性变化检测,如果容器发生了结构性变化,就会抛出 ConcurrentModificationException 异常,所以不能在迭代中直接调用容器类提供的 add/remove 方法。如需添加和删除,应调用迭代器的相关方法。