一文搞懂Java中的容器(集合类)

提示:本文介绍的集合类有很多,有的是日常开发常用的,有的是面试常问的,建议大家都了解一点。

文章目录

  • 一、容器的分类
  • 二、List、Set、Map 之间的区别是什么
  • 三、List
    • 1、ArrayList 和 LinkedList 的区别是什么?
    • 2、ArrayList 和 Vector 的区别是什么?
  • 四、Map
    • 1、HashMap 的实现原理
    • 2、HashMap 和 Hashtable 有什么区别?
    • 3、HashMap 和 TreeMap有什么区别?
  • 五、Iterator
    • 1、Iterator 是什么?
    • 2、Iterator 和 ListIterator 有什么区别?
    • 3、Iterator 怎么使用?有什么特点?
  • 总结


一、容器的分类

Java 容器分为 CollectionMap 两大类,其下又有很多子类,如下所示:
一文搞懂Java中的容器(集合类)_第1张图片

这里有个面试点:Collection 和 Collections 有什么区别?
Collection 是一个集合接口
Collections 是一个包装类,包含了很多静态方法,不能被实例化,就像一个工具类,比如提供的排序方法:Collections. sort(list)。

二、List、Set、Map 之间的区别是什么

一文搞懂Java中的容器(集合类)_第2张图片

三、List

1、ArrayList 和 LinkedList 的区别是什么?

  • 数据结构:ArrayList 是动态数组的数据结构实现,而 LinkedList 是双向链表的数据结构实现。
  • 查询效率:ArrayListLinkedList 在随机访问的时候效率要高,因为 LinkedList 是线性的数据存储方式,所以需要移动指针从前往后依次查找。
  • 增删效率:在非首尾的增加和删除操作,LinkedList 要比 ArrayList 效率要高,因为 ArrayList 增删操作要影响数组内的其他数据的下标。

综合来说,在需要频繁读取集合中的元素时,更推荐使用 ArrayList,而在插入和删除操作较多时,更推荐使用 LinkedList

2、ArrayList 和 Vector 的区别是什么?

  • 线程安全:Vector 使用了 Synchronized 来实现线程同步,是线程安全的,而 ArrayList 是非线程安全的。
  • 性能:ArrayList 在性能方面要优于 Vector,同样是因为Synchronized,每个操作都需要去获取锁。
  • 扩容:ArrayListVector 都会根据实际的需要动态的调整容量,只不过在 Vector 扩容每次会增加 1 倍,而 ArrayList 只会增加 50%

不推荐使用Vector性能非常低。在需要保证线程安全的场景下,可以使用Collections.synchronizedList()List 转为线程安全的 SynchronizedList。或者使用写时复制CopyOnWriteArrayList

四、Map

1、HashMap 的实现原理

HashMap的数据结构是数组 + 链表 + 红黑树,通过put(key,value)存储,get(key)来获取。在存储时,对key进行哈希计算得到哈希值,确定在数组中的位置,如果没有哈希冲突,直接可以存储元素。如果产生哈希冲突,会遍历链表,判断哈希值和key值,决定是修改还是插入链表末尾。

链表在默认配置下,超过8位会转成红黑树,增加效率。

HashMap扩容时会先把数组大小扩容为原数组的两倍,再对原数组的元素重新确定位置,转移到新数组中。

想要了解更详细的实现原理,源码等信息,请参考之前发布的《你真的懂HashMap吗???》一文

2、HashMap 和 Hashtable 有什么区别?

  • 存储:HashMapkeyvalue 都可以为 null,而 Hashtable 不允许。
  • 线程安全:Hashtable 使用了 Synchronized 来实现线程同步,是线程安全的,而 HashMap 是非线程安全的。

不推荐使用Hashtable性能非常低。在需要保证线程安全的场景下,可以使用ConcurrentHashMap,在Java 1.8 优化后,性能非常客观。

3、HashMap 和 TreeMap有什么区别?

  • 数据结构:HashMap的数据结构是 数组+链表+红黑树TreeMap的数据结构是红黑树
  • 实现接口:TreeMapHashMap 都继承自 AbstractMap ,但是需要注意的是 TreeMap 它还实现了 NavigableMap 接口和 SortedMap 接口,拥有对集合内元素的搜索能力和根据键key的排序能力。
  • 性能:HashMap适用于在Map中插入删除定位元素,Treemap适用于按自然顺序自定义顺序遍历键(key)。

五、Iterator

1、Iterator 是什么?

Iterator 接口提供遍历任何 Collection 的接口。我们可以从一个 Collection 中使用迭代器方法来获取迭代器实例。迭代器取代了 Java 集合框架中的 Enumeration,迭代器允许调用者在迭代过程中移除元素。

2、Iterator 和 ListIterator 有什么区别?

  • Iterator 可以遍历 SetList 集合,而 ListIterator 只能遍历 List
  • Iterator 只能单向遍历,而 ListIterator 可以双向遍历(向前/后遍历)。
  • ListIterator 继承 Iterator 接口,然后添加了一些额外的功能,比如添加一个元素、替换一个元素、获取前面或后面元素的索引位置

3、Iterator 怎么使用?有什么特点?

List<String> list = new ArrayList<>();
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()){
    String s = iterator.next();
    System.out.println(s);
}

Iterator的使用非常简单,通过集合的iterator()获取实例,根据hasNext()遍历元素。
Iterator 的特点是更加安全,因为它可以确保,在当前遍历的集合元素被更改的时候,就会抛出 ConcurrentModificationException 异常。


总结

Java中的容器在日常开发中使用频率非常高,根据不同的业务需求选择不同的容器非常重要,不仅可以提高性能,也能减少出错。但这需要对每个容器都有相对深入的理解。
希望我的分享能对你理解Java中的容器有所帮助。

你可能感兴趣的:(JAVA基础,java,面试,数据结构)