先来一张 集合 的 "家庭照"
Collection 是一个接口, 所有其子类 (也是接口) 需要重写其全部的方法!
特别说明:
Collection 和 Collections 长的太像了, 容易混淆, 这里就特别说明下:
Collection
Collection 是集合的顶级接口(Iterable 是 JDK1.5 新增), 其定义了一些必要方法. 如下:
- |-- iterator // 获取集合迭代器对象
- |-- size // 获取集合长度
- |-- add // 添加集合元素
- |-- addAll // 添加集合元素
- |-- remove // 删除集合元素
- |-- removeAll // 删除集合元素
- |-- clear // 清空集合元素
- |-- contains // 判断集合中是否包含某个元素
- |-- containsAll // 判断集合中是否包含某个元素
- |-- isEmpty // 判断集合是否有元素
- |-- equals // 判断两个集合是否相等
- |-- retainAll // 获取两个集合中相同的元素, 存到调用者的容器中, 相当于: 替换调用者原来的元素
- |-- hashCode // 获取集合哈希码值
- |-- toArray // 获取集合迭代器对象
- Collections
Collections 是一个包装类. 它包含有各种有关集合操作的静态多态方法.
此类不能实例化. 就像一个工具类, 服务于 Java 的 Collection 框架. 常用方法说明如下:
- |-- sort(List<T> list) // 对 List 集合进行排序(默认的是升序排列)(不适用与 Set 集合)
- |-- sort(List<T> list, Comparator<? super T> c) // 对 List 集合进行排序(可以传递自定义的比较器)(不适用与 Set 集合)
- |-- shuffle(List<?> list) // 对 List 集合中的元素进行随机排列
- |-- binarySearch(List<? extends T> list, T key) // 折半查找
- |-- reverse(List<?> list) // 反转 List 集合
- |-- reverseOrder() // 逆转对象的自然顺序 或 比较器
集合 Collection 派系介绍
List 派系
有序 (存, 取的顺序相同 - 怎么存, 怎么取)
有索引(可以通过索引精准操作数据)
允许存储重复元素
ArrayList
底层数据结构是: 一个长度可变的数组(数组本身长度不可变), 初始化的长度是 10(可变原理: 通过对数组的复制进行扩容, 扩容增长率: 50%).
线程不安全, 运行速度快
查询速度快, 增删速度慢
LinkedList
底层数据结构: 链表结构(采用对象之间的地址记录位置)
线程不安全, 运行速度快
查询速度慢, 增删速度快
Vector( Vector 被 ArrayList 取代)
底层数据结构是一个长度可变的数组(和 ArrayList 一样, 不同的是扩容增长率: 100%).
线程安全, 运行速度慢
查询速度快, 增删速度慢
Set 派系
无序 (存, 取顺序可能不一样)
无索引
不允许存储重复元素
HashSet(无序)
单重链接列表
底层数据结构: 哈希表(实际上是一个 HashMap 实例, 根据底层源码可得: 底层是一个 HashMap )
线程不安全, 运行速度快
LinkedHashSet(有序)
LinkedHashSet 始于 JDK1.4,Set 始于 JDK1.2
双重链接列表, 底层基于链表的哈希表实现
具有可预知迭代顺序(存, 取顺序一致)
线程不安全, 运行速度快, 存取速度快
TreeSet(有序且唯一)
底层数据结构基于: 红黑树
可以对存储的元素进行排序
线程不安全, 运行速度快
集合 Map 派系
采用了 Key-value 键值对映射的方式进行存储.
key 是无序, 唯一的, value 是无序不唯一的.
HashMap(无序)
底层数据结构: 哈希表
线程不安全, 运行速度快, 存取速度快
允许 存储'null'值,'null'键
LinkedHashMap
底层数据结构: 哈希表
键有迭代顺序(存, 取顺序一致)
线程不安全, 运行速度快
TreeMap(有序)
底层结构: 红黑树(可以按照对象的自然顺序进行排序)
键(对象): 必须要有自然顺序, 或采用比较器(作为键必须要有自然顺序或者使用了比较器, 否则会报错)
线程不安全, 运行速度快
HashTable( 无序, HashTable 被 HashMap 取代)
底层数据结构: 哈希表
键(对象): 必须重写方法: hashCode(),equals()
不允许存'null'( 键, 值 都不允许为'null', 若存'null', 编译时期不报错, 运行时期会抛出空指针异常 )
线程安全, 运行速度慢
Properties(无序)
底层数据结构: 哈希表
不允许重复键
存, 取顺序不确定(无序)
线程安全, 运行速度慢
常见的数据结构(数据存储方式)
栈: 数据 先进 后出
队列: 数据 先进 先出
数组: 按照索引进行存储
链表: 存储数据, 按照地址的记录方式存储(前面记住后面的 或 后面记住前面的 依次类推)
树: 存储的数据在容器中像树结构那样, 对象可以排序 (红黑树)
哈希表: 存储对象依赖对象的哈希值
Map 集合的迭代(遍历)
迭代步骤
使用集合的方法: iterator() 获取迭代器对象(获取的是 Iterator 接口的实现类对象).
使用迭代器对象, 调用方法 hasNext(),next() 进行集合的遍历.
迭代的两种方式
方式一: KeySet 方式(特点: 代码少, 原理简单, 开发中常用)
- HashMap<String, Integer> map = new HashMap<>();
- // 获取所有的键'key', 存储到 Set 集合中
- Set<String> keys = map.keySet();
- Iterator<String> iterator = keys.iterator();
- while (iterator.hasNext()) {
- String key = iterator.next();
- Integer value = map.get(key);
- }
方式二: entrySet 方式
- HashMap<String, String> map = new HashMap<>();
- Set<Map.Entry<String, String>> entries = map.entrySet();
- Iterator<Map.Entry<String, String>> iterator = entries.iterator();
- while (iterator.hasNext()) {
- Map.Entry<String, String> entry = iterator.next();
- String key = entry.getKey();
- String value = entry.getValue();
- }
迭代说明
获取迭代器对象, 迭代器对象内有一个值 lastRet(可以看成指针), 其原始值是 -1,
hasNext(): 指针判断是否有数据, 有返回 true, 没有返回 false
next(): 指针位置向后移动一位, 获取当前位置的数据并返回
特别注意: 一次 hasNext() 判断 只能有一次 next() 调用, 每调用一次 next() 指针都会向后移动一位!
- // 错误代码如示:
- while (iterator.hasNext()) {
- System.out.println(iterator.next()+"..."+map.get(iterator.next()));
- }
迭代原理
Collection 集合的每个实现类, 其内部是不同的. 故而对于每个集合子类, 它们存储对象的方式是不同的. 每个集合子类中定义一个内部类 (Itr) 去实现 Iterator 接口并重写方法, 各自实现查询, 获取的操作.
- // 以 ArrayList 为列, 其内部重写了 Collection 的方法 iterator()
- // 并返回实现了 Iterator 接口的内部类对象
- public Iterator<E> iterator() {
- return new Itr();
- }
- /************************************************************/
- //Java Iterator 接口源码中: 4 个方法 (能看到的只有 4 个)
- public interface Iterator<E> {
- // 查找集合中是否还有下一个元素, 有则返回 true, 没有返回 false
- boolean hasNext();
- // 返回集合中的下一个元素
- E next();
- // 遍历过程中, 移除集合中的元素
- default void remove() {
- throw new UnsupportedOperationException("remove");
- }
- default void forEachRemaining(Consumer<? super E> action) {
- Objects.requireNonNull(action);
- while (hasNext())
- action.accept(next());
- }
- }
Map 和 Collection 的区别( Map: 映射键值对 )
Map 并不继承于 Collection 接口 ( Map 和 Collection 都是顶级接口 )
Map 一个键对应一个值( 键不能重复, 值可以重复 )
Map: 所有的子接口或实现类, 存储对象的时候, 每次存储两个对象(键 和 值)(add)
Collection: 所有的子接口或实现类, 每次只能存储一个对象(值)(put)
Map 是双列的, Collection 是单列的
Array(数组)和 ArrayList(集合)的区别
数组: Array
表示形式: int[] array = new int[3] 或 int[] array = {1,2,3,4,5}
数据: 改, 查. 长度大小固定! 在内存中是连续的, 速度较快, 操作简单
集合: ArrayList
表示形式: ArrayList list = new ArrayList();
数据: 可 增, 删, 改, 查. 长度大小可动态增长
来源: http://www.bubuko.com/infodetail-3201590.html