Java集合框架-宏观总结
对 Java 集合框架部分的知识进行宏观的总结,主要涉及集合类的设计思想,以及集合类之间相互转换方法。
集合接口概况与设计思想
集合框架中最基础的是各种接口,主要分为两大类:
- java.util.Collection 接口
- 子接口包括 Set, SortedSet, List, Deque …
- java.util.Map 接口
- 不是真正的集合,但通过 collection-view 操作,可以像操作集合一样操作它;
- 子接口包括 SortedMap, NavigableMap, ConcurrentMap, ConcurrentNavigableMap.
1. 可修改性功能的实现
集合操作的核心是增删和查询。根据集合的可修改属性可以进行分类:
- 是否支持修改;unmodifiable与immutable的区别;
- 集合大小是否可以改变(List);
- 是否支持根据index快速获取元素(List);
- 是否支持随机获取元素(RandomAccess);
可以对一些集合类进行包装,来做到 unmodifiable,例如 Collections.unmodifiableInterface
, 返回被包装集合的一个不可修改的 view。
使用 Set, List 等的静态工厂方法 of() 也可以返回一个不可修改(immutable)的集合,如果尝试修改,会抛出一个 UnsupportedOperationException
。下面为Java Set 的of方法的源码:
1 | /** |
可以看到,实现 ImmutableCollection 的方法是在公开的 API 中,隐藏了他们的实现。
不在核心接口中直接设置集合是否可以修改,而是通过包装类或者工厂方法等生成不可修改的类,目的是保证核心接口、方法的简洁(类似网络的端到端原则)。
2. 互操作性
所有的集合表示之间都能够很好的进行互操作(interoperate)- 各种集合类型(包括数组)之间可以进行转换,从而可以更灵活的复用方法。
Collection接口 中,规定了大多数通用的集合间互相转换的方法。
addAll()
方法,addAll(Collection<? extends E> c)
- 需要关注的是顺序问题,如果List,则插在尾部;Deque, 插在尾部,= addLast()。
- List -
addAll(int index, Collection<? extends E> c
:在特定的index 处插入 Collection 类型的元素。
containsAll()
方法,传入参数为 集合类型,containsAll(Collection<?> c)
。removeAll(Collection<?> c)
,retainAll(Collection<?> c)
方法,删除所有集合中重复的值或者保留集合中重复的值(note: 可以快速的找出两个集合中重复的部分)。toArray()
方法:如果不传入参数,返回Object[]
类型;也可以如下传入参数,直接指定变为 array 后的类型:String[] y = x.toArray(new String[0]);
Note: Java 在 Collection 接口中定义了互操作的方法,在具体的子接口中,如果有需要,会对这些接口进行重写(override)及重载(overloading, e.g. list 的 addAll() 方法)。
Arrays类 中也提供了一些将数组与集合类型对象进行转换的静态方法。
asList()
, 返回List<T>
, 即将数组转为list, 元素类型通过 List 泛型进行保留。
但是需要注意的是,asList()
方法不能将基本数据类型的数组转为List,e.g.
1 | int[] tmp = {1,2,3,4,5}; |
Stackoverflow 上提供了几种将基本数据类型数组转为 List
的方法, ref
1 | // method 1- 循环遍历添加 |
Map 作为一种特殊的集合类型,与 Collection
接口之间没有继承关系。但可以通过一些方法转换为 集合类型 进行处理。
keySet()
方法,返回所有的 key 构成的集合,类型为Set<K>
。values()
方法,返回所有的 values 构成的集合,类型为Collection<V>
。entrySet()
方法,返回所有的条目构成的集合,类型为Set<Map.Entry<K,V>>
。
注意的是,上述方法返回的都称为 view,返回的结果背后的存储内容为 Map 中的内容。也就是说,上述方法使得我们可以使用 集合类(Collection, Set
接口)中的方法,查询、修改 Map 中的元素。(类似的返回 view 的还有 List 的 subList 等方法,通过修改返回的view,达到修改原对象的目的。)
需要注意的是,删除掉 Map 中的 entry、key、value 任何一项,对应的一条记录会被整个的删除。
1 | Map<Integer, String> map = new HashMap<>(); |
Tip: Map接口(包括其他的 Collection接口)都是从Java1.2开始出现的,Map接口用于取代之前版本中的抽象类 Dictionary。
Reference: