一、HashMap 类的介绍
HashMap<K, V>自Java 1.2以来就是Java集合的一部分。这个类可以在java.utils包找到。它提供了Java Map接口的基本实现
。它将数据存储在(Key, Value)对中,你可以通过另一种类型的索引(例如Integer)访问它们。一个对象用作另一个对象(值)的键(索引)。如果尝试插入重复的键
,它将替换对应键的元素
。
HashMap类似于HashTable,但它是不同步的
。它也允许存储空键
,但是应该只有一个空键对象
,并且可以有任意数量的空值。这个类不能保证映射的顺序。要使用这个类及其方法,需要导入java.util.HashMap包或它的超类。
HashMap 的重要特性:
- HashMap包含基于键的值。
- HashMap只包含
唯一的键
。 - HashMap扩展了抽象类AbstractMap,该抽象类还提供了Map接口的不完全实现。
- 它还实现了可克隆和可序列化接口。上面定义中的K和V分别代表Key和Value。
- HashMap可以有
一个空键和多个空值。
- HashMap是
非同步
的。 - HashMap
插入是无序
。 - HashMap类的
初始默认容量为16
,负载因子为0.75
。
HashMap的层次结构如下:
HashMap类声明:
public class HashMap<K,V> extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable
HashMap类参数:
- K:它是这个映射维护的键类型。
- V:映射值类型。
HashMap类的构造函数:
Constructor | Description |
---|---|
HashMap() | 它用于构造一个默认的HashMap。 |
HashMap(Map<? extends K,? extends V> m) | 它使用给定map对象m的元素来初始化哈希映射。 |
HashMap(int capacity) | 它用于将散列映射的容量初始化为给定的整数值capacity。 |
HashMap(int capacity, float loadFactor) | 它使用它的参数来初始化散列映射的容量和负载因子。 |
二、HashMap 类的外部操作
2.1添加操作
为了向映射添加元素,可以使用put()方法。但是,Hashmap中不保留插入顺序
。在内部,为每个元素生成一个单独的散列,并基于这个散列对元素进行索引,以提高效率。
实例:
public static void main(String[] args) {
HashMap<Integer, String> hm1 = new HashMap<>();
// 使用泛型初始化Map
HashMap<Integer, String> hm2 = new HashMap<Integer, String>();
// 插入元素
hm1.put(1, "深圳");
hm1.put(2, "广州");
hm1.put(3, "惠州");
hm2.put(new Integer(1), "江门");
hm2.put(new Integer(2), "香港");
hm2.put(new Integer(3), "佛山");
System.out.println(hm1);
System.out.println(hm2);
}
输出:
{1=深圳, 2=广州, 3=惠州}
{1=江门, 2=香港, 3=佛山}
2.2 修改操作
添加元素之后,如果我们希望更改元素,可以使用put()方法再次添加元素。由于映射中的元素是使用键建立索引的,因此键的值可以通过简单地插入我们想要更改的键的更新值来更改。
实例:
public static void main(String[] args) {
HashMap<Integer, String> hm1 = new HashMap<>();
// 插入元素
hm1.put(1, "深圳");
hm1.put(2, "广州");
hm1.put(3, "惠州");
System.out.println("修改前:"+hm1);
hm1.put(2,"北京");
System.out.println("修改后:"+hm1);
}
输出:
修改前:{1=深圳, 2=广州, 3=惠州}
修改后:{1=深圳, 2=北京, 3=惠州}
2.3 删除操作
可以使用Iterator接口遍历集合框架的任何结构。因为迭代器只处理一种类型的数据,所以我们使用Entry< ?,吗?以将两种不同的类型解析为兼容的格式。然后使用next()方法打印HashMap的条目。
实例:
public static void main(String[] args) {
HashMap<Integer, String> hm1 = new HashMap<>();
// 插入元素
hm1.put(1, "深圳");
hm1.put(2, "广州");
hm1.put(3, "惠州");
System.out.println("删除前:"+hm1);
hm1.remove(1);
System.out.println("删除后:"+hm1);
}
输出:
删除前:{1=深圳, 2=广州, 3=惠州}
删除后:{2=广州, 3=惠州}
2.4 遍历操作
实例:
public static void main(String[] args) {
HashMap<Integer, String> hm1 = new HashMap<>();
// 插入元素
hm1.put(1, "深圳");
hm1.put(2, "广州");
hm1.put(3, "惠州");
System.out.println("删除前:"+hm1);
for (Map.Entry<Integer,String > e : hm1.entrySet())
System.out.println("Key: " + e.getKey()
+ " Value: " + e.getValue());
}
输出:
删除前:{1=深圳, 2=广州, 3=惠州}
Key: 1 Value: 深圳
Key: 2 Value: 广州
Key: 3 Value: 惠州
三、HashMap 类的 内部结构
HashMap内部包含一个Node数组,一个Node被表示为一个包含4个字段的类:
- int hash
- K key
- V value
- Node next
可以看到,节点包含对自己对象的引用。所以它是一个链表。
HashMap:
Node:
HashMap的性能
HashMap的性能取决于两个参数,名称如下:
- 初始容量(Initial Capacity)
- 负载因子(Load Factor)
待续