Map 是最常用的数据结构之一.
Map 的字面翻译是映射(地图就是一种映射).
本文将为你展示如何使用各种不同的map,包括 HashMap, TreeMap, HashTable 以及 LinkedHashMap.
1. Map 概述
图1
在JavaSE中,对Map的实现主要包括: HashMap, TreeMap, HashTable 和 LinkedHashMap.
如果每个类都用一句话来描述,则表述如下:
- HashMap 使用哈希表(hash table)实现, 在 keys 和/或 values 之中,都是无序的.
- TreeMap 基于红黑树(red-black tree)数据结构实现, 按 key 排序.
- LinkedHashMap 保持者插入顺序.
- Hashtable 与HashMap实现方式一样,但Hashtable属于同步(synchronized)的.
2. HashMap
如果HashMap中的key使用的是自定义的类对象,那么需要遵守 equals() 与 hashCode() 规范.
- class Dog {
- String color;
- Dog(String c) {
- color = c;
- }
- public String toString(){
- return color + " dog";
- }
- }
- public class TestHashMap {
- public static void main(String[] args) {
- HashMap<Dog, Integer> hashMap = new HashMap<Dog, Integer>();
- Dog d1 = new Dog("red");
- Dog d2 = new Dog("black");
- Dog d3 = new Dog("white");
- Dog d4 = new Dog("white");
- hashMap.put(d1, 10);
- hashMap.put(d2, 15);
- hashMap.put(d3, 5);
- hashMap.put(d4, 20);
- //print size
- System.out.println(hashMap.size());
- //loop HashMap
- for (Entry<Dog, Integer> entry : hashMap.entrySet()) {
- System.out.println(entry.getKey().toString() + " - " + entry.getValue());
- }
- }
- }
- 4
- white dog – 5
- black dog – 15
- red dog – 10
- white dog – 20
修正后的 Dog 类如下所示:
- class Dog {
- String color;
- Dog(String c) {
- color = c;
- }
- public boolean equals(Object o) {
- return ((Dog) o).color == this.color;
- }
- public int hashCode() {
- return color.length();
- }
- public String toString(){
- return color + " dog";
- }
- }
- 3
- red dog – 10
- white dog – 20
- black dog – 15
如果没有重写,使用的就会是 Object 类实现的 hashCode() 和 equals() 方法
默认的 hashCode() 方法实现对每个不同的对象返回不同的整数.
默认的 equals() 方法只比较两个引用是否指向同一个实际对象.
如果你还有疑惑,请阅读: equals()与hashCode()方法协作约定
3. TreeMap
TreeMap是根据key排序的.我们先看下面的示例来加深 "按key排序" 的印象.
- class Dog {
- String color;
- Dog(String c) {
- color = c;
- }
- public boolean equals(Object o) {
- return ((Dog) o).color == this.color;
- }
- public int hashCode() {
- return color.length();
- }
- public String toString(){
- return color + " dog";
- }
- }
- public class TestTreeMap {
- public static void main(String[] args) {
- Dog d1 = new Dog("red");
- Dog d2 = new Dog("black");
- Dog d3 = new Dog("white");
- Dog d4 = new Dog("white");
- TreeMap<Dog, Integer> treeMap = new TreeMap<Dog, Integer>();
- treeMap.put(d1, 10);
- treeMap.put(d2, 15);
- treeMap.put(d3, 5);
- treeMap.put(d4, 20);
- for (Entry<Dog, Integer> entry : treeMap.entrySet()) {
- System.out.println(entry.getKey() + " - " + entry.getValue());
- }
- }
- }
- Exception in thread “main” java.lang.ClassCastException: collection.Dog cannot be cast to java.lang.Comparable
- at java.util.TreeMap.put(Unknown Source)
- at collection.TestHashMap.main(TestHashMap.java:35)
当然,你也可以使用 String 对象作为key,因为 String 类已经实现了 Comparable 接口。
下面,我们修改 Dog 类的代码,使其实现Comparable:
- class Dog implements Comparable<Dog>{
- String color;
- int size;
- Dog(String c, int s) {
- color = c;
- size = s;
- }
- public String toString(){
- return color + " dog";
- }
- @Override
- public int compareTo(Dog o) {
- return o.size - this.size;
- }
- }
- public class TestTreeMap {
- public static void main(String[] args) {
- Dog d1 = new Dog("red", 30);
- Dog d2 = new Dog("black", 20);
- Dog d3 = new Dog("white", 10);
- Dog d4 = new Dog("white", 10);
- TreeMap<Dog, Integer> treeMap = new TreeMap<Dog, Integer>();
- treeMap.put(d1, 10);
- treeMap.put(d2, 15);
- treeMap.put(d3, 5);
- treeMap.put(d4, 20);
- for (Entry<Dog, Integer> entry : treeMap.entrySet()) {
- System.out.println(entry.getKey() + " - " + entry.getValue());
- }
- }
- }
- red dog – 10
- black dog – 15
- white dog – 20
如果我们把
" Dog d4 = new Dog("white", 10); "
这一行代码替换为
" Dog d4 = new Dog("white", 40); "
那么,执行后的结果为:
- white dog – 20
- red dog – 10
- black dog – 15
- white dog – 5
4. Hashtable
根据Java文档, HashMap 类基本上等同于 Hashtable, 区别仅仅在于: HashMap 不是同步的,并且运行 null 值.
5. LinkedHashMap
LinkedHashMap 是 HashMap 的子类. 所以继承了所有 HashMap 的特性,另外, 链表保持了插入的顺序.
我们复制上面的 HashMap 的示例代码,并将HashMap替换为LinkedHashMap:
- class Dog {
- String color;
- Dog(String c) {
- color = c;
- }
- public boolean equals(Object o) {
- return ((Dog) o).color == this.color;
- }
- public int hashCode() {
- return color.length();
- }
- public String toString(){
- return color + " dog";
- }
- }
- public class TestHashMap {
- public static void main(String[] args) {
- Dog d1 = new Dog("red");
- Dog d2 = new Dog("black");
- Dog d3 = new Dog("white");
- Dog d4 = new Dog("white");
- LinkedHashMap<Dog, Integer> linkedHashMap = new LinkedHashMap<Dog, Integer>();
- linkedHashMap.put(d1, 10);
- linkedHashMap.put(d2, 15);
- linkedHashMap.put(d3, 5);
- linkedHashMap.put(d4, 20);
- for (Entry<Dog, Integer> entry : linkedHashMap.entrySet()) {
- System.out.println(entry.getKey() + " - " + entry.getValue());
- }
- }
- }
- red dog – 10
- black dog – 15
- white dog – 20
下面再次列出使用 HashMap的输出结果以供对比:
- red dog – 10
- white dog – 20
- black dog – 15