Java 容器面试一
Java 容器综合
Java 容器框架概览
Java 容器框架主要分为 Collection
和 Map
两种。其中,Collection
又分为 List
、Set
以及 Queue
。
Java 容器框架主要分为 Collection
和 Map
两种。其中,Collection
又分为 List
、Set
以及 Queue
。
《阿里巴巴 Java 开发手册》的描述如下:
判断所有集合内部的元素是否为空,使用
isEmpty()
方法,而不是size()==0
的方式。
这是因为 isEmpty()
方法的可读性更好,并且时间复杂度为 O(1)。
绝大部分我们使用的集合的 size()
方法的时间复杂度也是 O(1),不过,也有很多复杂度不是 O(1) 的,比如 java.util.concurrent
包下的某些集合(ConcurrentLinkedQueue
、ConcurrentHashMap
...)。
Hashtable 是早期 Java 类库提供的一个哈希表实现,本身是同步的,不支持 null 键和值,由于同步导致的性能开销,所以已经很少被推荐使用。
HashMap 是应用更加广泛的哈希表实现,行为上大致上与 HashTable 一致,主要区别在于 HashMap 不是同步的,支持 null 键和值等。
二者的主要差别如下:
HashMap | Hashtable | |
---|---|---|
线程安全 | 非线程安全 | 线程安全(主要方法都用 synchronized 修饰) |
效率 | 性能好 | 性能差:互斥锁,势必影响性能 |
初始化容量 | 初始容量为 16 | 初始容量为 11 |
扩容方式 | 2N(N 为当前容量) | 2N + 1 |
是否允许空值 | 允许存储 null 的 key 和 value | 不允许存储 null 的 key 和 value |
在 Java8 中,Collection
新增了两个流方法,分别是 stream()
和 parallelStream()
。
Stream
相当于高级版的 Iterator
,他可以通过 Lambda 表达式对集合进行各种非常便利、高效的聚合操作(Aggregate Operation),或者大批量数据操作 (Bulk Data Operation)。
Java 容器涉及许多数据结构知识点,所以设立专题进行总结。
泛型
、Iterable
、Iterator
、Comparable
、Comparator
、Cloneable
、fail-fast
List
、ArrayList
、LinkedList
Map
、HashMap
、TreeMap
、LinkedHashMap
、WeakHashMap
Set
、HashSet
、TreeSet
、LinkedHashSet
、EmumSet
Queue
、Deque
、ArrayDeque
、LinkedList
、PriorityQueue
Queue
接口定义如下:
public interface Queue<E> extends Collection<E> {}
在 Java 中,同步容器主要包括 2 类:
Vector
、Stack
、Hashtable
Vector
- Vector
实现了 List
接口。Vector
实际上就是一个数组,和 ArrayList
类似。但是 Vector
中的方法都是 synchronized
方法,即进行了同步措施。Stack
- Stack
也是一个同步容器,它的方法也用 synchronized
进行了同步,它实际上是继承于 Vector
类。Hashtable
- Hashtable
实现了 Map
接口,它和 HashMap
很相似,但是 Hashtable
进行了同步处理,而 HashMap
没有。Collections
类中提供的静态工厂方法创建的类(由 Collections.synchronizedXXX
等方法)Map 家族主要成员功能如下:
Map
是 Map 容器家族的祖先,Map 是一个用于保存键值对(key-value)的接口。Map 中不能包含重复的键;每个键最多只能映射到一个值。AbstractMap
继承了 Map
的抽象类,它实现了 Map
中的核心 API。其它 Map
的实现类可以通过继承 AbstractMap
来减少重复编码。SortedMap
继承了 Map
的接口。SortedMap
中的内容是排序的键值对,排序的方法是通过实现比较器(Comparator
)完成的。NavigableMap
继承了 SortedMap
的接口。相比于 SortedMap
,NavigableMap
有一系列的“导航”方法;如"获取大于/等于某对象的键值对"、“获取小于/等于某对象的键值对”等等。HashMap
继承了 AbstractMap
,但没实现 NavigableMap
接口。HashMap
的主要作用是储存无序的键值对,而 Hash
也体现了它的查找效率很高。HashMap
是使用最广泛的 Map
。Hashtable
虽然没有继承 AbstractMap
,但它继承了 Dictionary
(Dictionary
也是键值对的接口),而且也实现 Map
接口。因此,Hashtable
的主要作用是储存无序的键值对。和 HashMap 相比,Hashtable
在它的主要方法中使用 synchronized
关键字修饰,来保证线程安全。但是,由于它的锁粒度太大,非常影响读写速度,所以,现代 Java 程序几乎不会使用 Hashtable
,如果需要保证线程安全,一般会用 ConcurrentHashMap
来替代。TreeMap
继承了 AbstractMap
,且实现了 NavigableMap
接口。TreeMap
的主要作用是储存有序的键值对,排序依据根据元素类型的 Comparator
而定。WeakHashMap
继承了 AbstractMap
。WeakHashMap
的键是弱引用 (即 WeakReference
),它的主要作用是当 GC 内存不足时,会自动将 WeakHashMap
中的 key 回收,这避免了 WeakHashMap
的内存空间无限膨胀。很明显,WeakHashMap
适用于作为缓存。Set 家族成员简介:
Set
继承了 Collection
的接口。实际上 Set
就是 Collection
,只是行为略有不同:Set
集合不允许有重复元素。SortedSet
继承了 Set
的接口。SortedSet
中的内容是排序的唯一值,排序的方法是通过比较器(Comparator)。NavigableSet
继承了 SortedSet
的接口。它提供了丰富的查找方法:如"获取大于/等于某值的元素"、“获取小于/等于某值的元素”等等。AbstractSet
是一个抽象类,它继承于 AbstractCollection
,AbstractCollection
实现了 Set 中的绝大部分方法,为实现 Set
的实例类提供了便利。HashSet
类依赖于 HashMap
,它实际上是通过 HashMap
实现的。HashSet
中的元素是无序的、散列的。TreeSet
类依赖于 TreeMap
,它实际上是通过 TreeMap
实现的。TreeSet
中的元素是有序的,它是按自然排序或者用户指定比较器排序的 Set。LinkedHashSet
是按插入顺序排序的 Set。EnumSet
是只能存放 Emum 枚举类型的 Set。Java 中常用的存储容器就是数组和容器,二者有以下区别: