早在 Java 2 中之前,Java 就提供了特设类。比如:Dictionary, Vector, Stack 和 Properties 这些类用来存储和操作对象组。虽然这些类都非常有用,但是它们缺少一个核心的,统一的主题。由于这个原因,使用 Vector 类的方式和使用 Properties 类的方式有着很大不同。为此,整个集合框架就围绕一组标准接口而设计。
集合框架被设计成要满足以下几个目标。
graph LR
Collection接口-->List接口
Map接口-->HashMap类
Collection接口-->Set接口
List接口-->ArrayList类
List接口-->LinkedList类
Set接口-->HashSet类
Set接口-->SortedSet类
Map接口-->SortedMap类
SortedMap类-->TreeMap类
HashSet类-->LinkedHashSet类
SortedSet类-->TreeSet类
Iterator接口-->ListIterator接口
最基本的集合接口,存储一组不唯一、无序的对象
公共方法
方法 | 描述 |
---|---|
int size() | 返回元素个数 |
boolean isEmpty() | 判断是否为空 |
boolean contains(Object obj) | 判断是否包含 obj |
boolean add(E element) | 添加元素,返回成功与否 |
int hashCode() | 返回哈希码 |
Object[] toArray() | 转换为 Object 数组 |
boolean remove(Object obj) | 删除元素 |
void clear() | 清空容器 |
Iterator | 返回迭代器 |
boolean equals(Object o) | 是否与 o 相等 |
void shuffle(List< ? > list) | 随机重排元素 |
boolean containsAll(Collection< ? > c) | 判断是否包含 c 中所有元素 |
boolean addAll(Contain< ? > c) | 集合并运算 |
boolean removeAll(Collection< ? > c) | 集合差运算 |
boolean retainAll(Collection< ? > c) | 集合交运算,只保留也被 c 包含的元素 |
存储键值对,提供 key 到 value 的映射,key 唯一
公共方法
方法 | 描述 |
---|---|
V put(K key,V value) | 插入键值对 |
void putAll(Map<? extends K,? extends V> m) | 复制映射 |
boolean containsKey(Object key) | 判断是否包含 key |
boolean containsValue(Object value) | 判断是否包含 value |
V get(Object key) | 返回键对应值 |
Set | 返回键的集合 |
Collection | 返回值的集合 |
V remove(Object key) | 删除 key 对应条目 |
Set<Map.Entry<K,V>> entrySet() | 返回键值对的集合 |
使用 keySet() 抽取 key 序列,将 map 中的所有 key 生成一个 Set。
使用 values() 抽取 value 序列,将 map 中的所有 values 生成一个 Collection。
为什么一个生成 Set,一个生成 Collection?那是因为,key 总是独一无二的,value 允许重复。
Collection 的子接口,通过索引访问元素,存储一组不唯一、有序的对象
公共方法
方法 | 描述 |
---|---|
E get(int index) | 返回指定位置元素 |
E set(int index,E element) | 替换指定位置,返回被取代元素 |
int indexOf(Object o) | 返回 o 首次出现序号,不存在返回 -1 |
int lastIndexOf(Object o) | 返回 o 最后出现序号 |
void add(int index,E element) | 指定位置插入 |
boolean add(E element) | 最后位置插入 |
E remove(int index) | 删除并返回指定位置元素 |
boolean addAll(Collection<? extends E> c) | 列表最后添加 c 中所有元素 |
boolean addAll(int index,Collection<? extends E> c) | 指定位置添加 c 中所有元素 |
ListIterator | 返回迭代器 |
ListIterator | 返回指定位置开始的迭代器 |
ArrayList
数组列表,自动扩容,增长长度为原来的 50%
基于数组,随机访问、遍历效率高,插入删除效率低
可插入 null
LiinkedList
链式数据结构
基于双向链表,插入删除效率高,随机访问、查找效率低
可插入 null
常用方法
方法 | 描述 |
---|---|
public void addFirst(E e) | 插入开头 |
public void addLast(E e) | 插入尾部 |
public E getFirst() | 返回第一元素 |
public E getLast() | 返回最后元素 |
public E removeFirst() | 删除并返回第一元素 |
public E removeLast() | 删除并返回最后元素 |
HashMap
TreeMap
基于二叉搜索树,查找元素时间复杂度 O(logn)
实现了 SortedMap 接口
不允许 null 键(空指针异常),允许 null 值
键必须唯一,值可以重复,按键值从大到小排列
常用方法
方法 | 描述 |
---|---|
public K firstKey() | 返回最低键 |
public K lastKey() | 返回最高键 |
public SortedMap<K,V> headMap(K toKey) | 返回键值小于 toKey 那部分映射 |
public SortedMap<K,V> tailMap(K toKey) | 返回大于等于 toKey 那部分映射 |
public K lowerKey(K key) | 返回小于给定键的最大键 |
public K floorKey(K key) | 返回小于等于给定键的最大键 |
public K higherKey(K key) | 返回大于给定键的最小键 |
public K ceilingKey(K key) | 返回大于等于给定键的最小键 |
HashSet
方法 | 描述 |
---|---|
public boolean add(E e) | 添加对象,返回成功与否 |
public void clear() | 清空集合 |
public boolean contains(Object o) | 判断是否包含 o 元素 |
public int size() | 返回集合容量 |
TreeSet
LinkedHashset
继承自 HashMap,内部加入链表保存元素顺序
基于元素进入集合的顺序或者被访问的顺序排序
HashTable
Vector
Properties
继承自 HashTable,实现了 Map 接口
表示一个持久的属性集,属性列表中每个键及其对应值都是一个字符串
常用方法
方法 | 描述 |
---|---|
String getProperty(String key) | 返回指定键对应属性 |
Object setProperty(String key, String value) | 调用 Hashtable 的 put 方法 |
void list(PrintStream streamOut) | 将属性列表输出到指定的输出流 |
void list(PrintWriter streamOut) | 将属性列表输出到指定的输出流 |
void load(InputStream streamIn) throws IOException | 从输入流中读取属性列表 |
//加载 properties 配置文件的两种方法,JDBCUtils 为例
//方法一
URL res = JDBCUtils.class.getClassLoader().getResource("jdbc.properties");
String path = res.getPath();
pro.load(new FileReader(URLDecoder.decode(path, "utf-8")));
//方法二
// InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
InputStream is = JDBCUtils.class.getResourceAsStream("/jdbc.properties");
pro.load(is);
Stack
继承自 Vector ,先进后出
线程安全
常用方法
方法 | 描述 |
---|---|
boolean empty() | 判断是否栈空 |
Object peek() | 查看栈顶元素,不删除 |
Object pop() | 删除栈顶元素,并返回 |
Object push(Object element) | 元素压栈 |
int search(Object element) | 返回位置,以 1 为基数 |
Dictionary
BitSet
位集合, 按需增长的位向量
使用场景:整数,无重复
每一位的值都是一个 boolean 值 ,占用一 bit(不是一字节)
内部基于 long 数组, 所以 BitSet 的大小为 long 类型大小(64位)的整数倍
常用方法
方法 | 描述 |
---|---|
void set(int index) | 将指定索引处的位设置为 true |
void set(int index, boolean v) | 将指定索引处的位设置为指定值 |
void set(int startIndex, int endIndex) | 将范围内的位设置为 true(左开右闭) |
void set(int startIndex, int endIndex, boolean v) | 将范围内的位设置为指定值(左开右闭) |
boolean get(int index) | 返回指定索引处的位值 |
方法 | 描述 |
---|---|
Collections.reverse(List l) | 反转 |
Collections.shuffle(List l) | 混淆 |
Collections.sort(List l) | 排序 |
Collections.swap(List l,int index1,int index2) | 替换下标位置元素 |
Collections.rotate(List l,int step) | 向右滚动 ,尾部移动到开头 |
Collections.synchronizedList() | 线程安全化 |
Collections.fill(List l,Object o) | 填充 |
Collections.copy(List m,List n) | n 中的元素复制到 m 中,并覆盖相应索引的元素 |
Collection 定义了 toArray()、iterator()、size()方法,但并非所有实现类都重写了这些方法,Set 不提供 get 方法,不能使用 size() 方式遍历。
//Set 遍历方式
Set<String> set = new HashSet<String>();
//迭代器遍历
Iterator<String> it = set.iterator();
while (it.hasNext())
{
String str = it.next();
System.out.println(str);
}
//for循环遍历:
for (String str : set)
System.out.println(str);
Iterator 接口常用方法
方法 | 描述 |
---|---|
public abstract boolean hasNext() | 判断是否还有后续元素 |
public abstract E next() | 返回后续元素 |
public abstract void remove() | 删除当前指向元素 |
ListIterator 接口常用方法
方法 | 描述 |
---|---|
public abstract boolean hashPrevious() | 判断是否有前驱元素 |
public abstract E previous() | 返回前驱元素 |
public abstract add(E e) | 插入 next() 返回值之前,previoous() 之后 |
public abstract set(E e) | 替换当前指向元素 |
public abstract int nextIndex() | 返回基于 next() 元素序号 |
public abstract int previousIndex() | 返回基于 previous() 元素序号 |
数组复制
public static <T,U> T[] copyOfRange(U[] original, int from, int to)
original:原数组 from:原数组的起始位置 to:终点位置(不包括)
public static <T> T[] copyOf(T[] original, int newLength)
original:原数组 newLength:要复制的长度
StringBuider 中底层数组的扩容使用了 copyOf()
copyOf() 内部是通过 System.arraycopy() 实现的
System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
src:原数组 srcPos:原数组起始位置
dest:目标数组 destPost:目标数组的起始位置 length:复制长度
List 中的 remove 方法使用了 arraycopy()
其他方法
方法 | 描述 |
---|---|
public static String toString() | 转换为字符串 |
public static void sort() | 排序 |
public static int binarySearch(Object[] a, Object key ) | 搜索 |
public static boolean equals(long[] a, long[] b) | 判断是否相同 |
public static void fill(int[] a, int val)) | 填充 |
哈希集合查找元素为时间复杂度为 O(1) 的原理
获得散列值:
通过特定的哈希函数,每个对象都有对应的哈希值、
hashcode对应到内存地址:
可以使用一个数组 array,将要存的数据放在 array[hashcode] 位置上
哈希碰撞
通过哈希方法,两个不同的元素,获得了相同的哈希值
最常用用的解决办法是拉链法,在同一地址上建立链表来存储多个 hashcode 相同的元素
查找
通过哈希值找到地址,若地址上有多个元素,则用 equals 判断存储位置是否相同
对于哈希集合来说,如果重写了元素对应的 equals() 方法或 hashcode() 方法中的一个,也必须重写另一个