HashMap
采用 Hash 算法存储数据,key不可以重复,Value可以重复,当存入的元素的 Key 在 Map 中已经存在,则会覆盖原来的值。初始默认大小是16,负载因子0.75(当数据量超过容量的 75% 时进行扩容)
常用方法
方法 | 描述 |
---|---|
clear() | 删除 hashMap 中的所有键/值对 |
clone() | 复制一份 hashMap |
isEmpty() | 判断 hashMap 是否为空 |
size() | 计算 hashMap 中键/值对的数量 |
put() | 将键/值对添加到 hashMap 中 |
putAll() | 将所有键/值对添加到 hashMap 中 |
putIfAbsent() | 如果 hashMap 中不存在指定的键,则将指定的键/值对插入到 hashMap 中。 |
remove() | 删除 hashMap 中指定键 key 的映射关系 |
containsKey() | 检查 hashMap 中是否存在指定的 key 对应的映射关系。 |
containsValue() | 检查 hashMap 中是否存在指定的 value 对应的映射关系。 |
replace() | 替换 hashMap 中是指定的 key 对应的 value。 |
replaceAll() | 将 hashMap 中的所有映射关系替换成给定的函数所执行的结果。 |
get() | 获取指定 key 对应对 value |
getOrDefault() | 获取指定 key 对应对 value,如果找不到 key ,则返回设置的默认值 |
forEach() | 对 hashMap 中的每个映射执行指定的操作。 |
entrySet() | 返回 hashMap 中所有映射项的集合集合视图。 |
keySet | 返回 hashMap 中所有 key 组成的集合视图。 |
values() | 返回 hashMap 中存在的所有 value 值。 |
merge() | 添加键值对到 hashMap 中 |
compute() | 对 hashMap 中指定 key 的值进行重新计算 |
computeIfAbsent() | 对 hashMap 中指定 key 的值进行重新计算,如果不存在这个 key,则添加到 hashMap 中 |
computeIfPresent() | 对 hashMap 中指定 key 的值进行重新计算,前提是该 key 存在于 hashMap 中。 |
常见遍历方式
Set<Map.Entry<String, String>> entries = mp.entrySet();
for(Map.Entry<String, String> entry : entries) {
System.out.println(entry.getKey());
System.out.println(entry.getValue());
}
LinkedHashMap
继承自 HashMap,有顺序(插入顺序),底层实现和 LinkedHashSet 一样,都是维护一个散列表和一个链表
特性:有序性,Key唯一性,Value值不唯一
TreeMap
底层采用树的结构,会按照 Key 大小默认升序排列
Hashtable
他的功能和 HashMap 差不多,但是由于效率低于 HashMap 所以使用比较少,有个优点就是他是线程安全的,其中面试问的比较多的就是他和 HashMap 的区别
Hashtable 和 HashMap 的异同
- 都实现了 Map 接口
- Hashtable 是基于陈旧的 Dictionary 类的,在 JDk1.0 加入,而HashMap 实在 JDK1.2 加入的
- Hashtable 线程安全,HashMap 非线程安全
- Hashtable 的 Key 或者 Vule 不允许存在 null,HashMap 可以
- HashMap 的初始容量是 16,Hashtable 初始容量是 11,加载因子都是 0.75
- HashMap 扩容是 capacity * 2,Hashtable 扩容是 capacity * 2 + 1
- HashMap 底层数据结构:数组 + 链表 + 红黑树(当链表的长度大于 8 时,转为红黑树的结构),Hashtable 数据结构:数组 + 链表
- 计算 hash 的方式不同
- Hashtable 计算 hash 直接使用 Key 的 HashCode 对 table数组的长度进行取模,
- HashMap 计算 hash 对 key 的 HashCode 进行二次 hash,以获得更好的的散列值,然后对数组长度取余
Properties
继承自 Hashtable,用于处理属性配置文件的
- 方式一:通过 Properties 类获取
Properties properties = new Properties();
properties.load(Main.class.getClassLoader().getResourceAsStream("config/user.properties"));
//根据键获取值
String userName = properties.getProperty("userName");
String age = properties.getProperty("age");
// 直接获取所有键值对
Set<Map.Entry<Object, Object>> entries = properties.entrySet();
- 方式二:通过 ResourceBundle 类获取
//只写文件名不要写后缀
ResourceBundle bundle = ResourceBundle.getBundle("config/User");
String userName = bundle.getString("userName");
String password = bundle.getString("password");
Stack
栈是Vector的一个子类,它实现了一个标准的后进先出的栈。堆栈只定义了默认构造函数,用来创建一个空栈。 堆栈除了包括由Vector定义的所有方法,也定义了自己的一些方法。
常用方法
序号 | 方法描述 |
---|---|
1 | boolean empty() 测试堆栈是否为空。 |
2 | Object peek( ) 查看堆栈顶部的对象,但不从堆栈中移除它。 |
3 | Object pop( ) 移除堆栈顶部的对象,并作为此函数的值返回该对象。 |
4 | Object push(Object element) 把项压入堆栈顶部。 |
5 | int search(Object element) 返回对象在堆栈中的位置,以 1 为基数。 |
Queue 接口
简介
队列是一种特殊的线性表,它只允许在表的前端进行删除操作,而在表的后端进行插入操作。LinkedList类实现了Queue接口,因此我们可以把LinkedList当成Queue来用。除了基本的集合接口操作外,队列还提供了特殊的插入,删除,获取的操作。就是当集合不存在元素时不是抛出异常而是返回 null 或者 false,我们可以根据业务需求灵活选择
常用实现类
- LinkedList
LinkedList类实现了Queue接口,因此它可以作为队列使用。由于其内部使用双向链表实现,所以插入和删除操作都具有较高的效率。
- ArrayDeque
ArrayDeque是一个双端队列,实现了Queue接口,也可以当作栈来使用。它通常比LinkedList提供更高的性能,是并发编程中首选的队列实现之一。
常用方法
抛出异常的方法 | 返回 null 或者 false 的方法 | |
---|---|---|
插入 | add(e) | offer(e) |
移除 | remove() | poll() |
获取 | element() | peek() |
Deque 接口
它的功能可以完美替代 Stack,并且效率要高于 Stack,所以对于要使用栈的业务推荐使用Deque,与队列的差别在于它可以头部入队头部出队,尾部入队尾部出队
实现类
- ArrayDeque
ArrayDeque是一个双端队列,实现了Queue接口,也可以当作栈来使用。它通常比LinkedList提供更高的性能,是并发编程中首选的队列实现之一。