HashMap、TreeMap、Hashtable、LinkedHashMap四者比较

翻译 2013年12月04日 22:04:26

    Map是一种很重要的数据结构。在本文中,我会告诉你们如何使用HashMap、TreeMap、Hashtable、LinkedHashMap这四种map。

1. Map概览


    在Java SE中,Map有四种常用的实现:HashMap、TreeMap、Hashtable和LinkedHashMap。我们可以使用一句话来分别描述各种实现,如下:

    ① HashMap是作为哈希表(hash table)实现的,其中的键(key)和值(value)没有顺序。

    ② TreeMap是基于红黑树(red-black tree)结构实现的,其中的元素根据键(key)进行排序。

    ③ LinkedHashMap保留了元素的插入顺序。

    ④ Hashtable是同步的,这一点和HashMap不同。

    因此,在线程安全(thread-safe)的情况下,应使用HashMap,因为Hashtable需要额外的同步开销。

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
    这里请注意,我们添加两次”white dogs“,这本该是个错误,但HashMap却照常执行。这就有点儿说不通了,我们现在不知道到底有多少”white dogs“。
    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
    究其原因,HashMap中不允许存在两个完全相同的元素。默认的,Object类中的hashCode()和equals()方法会被调用。默认的hashCode()方法为不同的对象分配不同的增速,而当两个变量引用同一个对象时,equals()方法返回true。如果你对此了解的不是特别清楚,请查看文章《the hashCode() and equals() contract》

    查看文章《the most frequently used methods for HashMap》,如iteration、print等等。

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)
    由于TreeMap是按照键(key)进行排序的,用来当做键的对象相互之间必须能够进行大小比较,所以它必须实现Comparable接口。例如,你可以将String作为键,因为String实现了Comparable接口。

    我们来修改一下Dog类,使它可以进行大小比较。

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
    在本例中,TreeMap是按照键dog size进行排序的。

    如果“Dog d4 = new Dog("white", 10);”被替换为“Dog d4 = new Dog("white", 40);”,那么输出的结果会变成:

white dog – 20
red dog – 10
black dog – 15
white dog – 5
    因为TreeMap使用compareTo()方法来比较键,因此不同size的dog被认为是不相同的。

4. Hashtable

    来自Java文档:HashMap类与Hashtable基本相同,但HashMap不是同步的,而且允许空值作为key或value。

5. LinkedHashMap

    LinkedHashMap是HashMap的子类,这意味着它继承了HashMap的特性。而且,LinkedHashMap中的链表确保了元素的插入有序。

    我们将上面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

原文地址:HashMap vs. TreeMap vs. HashTable vs. LinkedHashMap

HashMap TreeMap Hashtable LinkedHashMap 区别

map是java中最常用的数据结构之一,在这篇文中,我将说明如何使用不同类型的maps,比如:HashMap,TreeMap,HashTable和LinkedHashMap。 Map概览 在jav...
  • maoyeqiu
  • maoyeqiu
  • 2015年09月27日 14:18
  • 1288

【Java集合之Map】HashMap、HashTable、TreeMap、LinkedHashMap区别

前言ArrayList和LinkedList都实现了List接口,大致区别如下: ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。 对于随机访问get和se...
  • cyh1111
  • cyh1111
  • 2016年12月20日 13:03
  • 1167

HashMap,HashTable,TreeMap,WeakHashMap有哪些区别?

Java 为数据结构中的映射文件定义了一个接口java.util.Map,它包含了三个实现类  HashMap,HashTable,TreeMap. Map是用来存放键值对的数据结构,在数组中通过数...
  • JohnLee_chun
  • JohnLee_chun
  • 2016年09月17日 15:34
  • 306

从源代码看TreeMap、HashMap、Hashtable、ConcurrentHashMap、LinkedHashMap特性

TreeMap、HashMap、Hashtable、ConcurrentHashMap、LinkedHashMap 这几个都是Map的实现类,但是都有各自的特点: HashMap是基于Hash...
  • fzhsh
  • fzhsh
  • 2016年04月22日 23:50
  • 1079

Java集合学习--HashMap、LinkedHashMap、TreeMap、HashTable

HashMap: 初始化: HashMap中有两个因子影响其性能:初始容量和加载因子。这两个参数都可以在创建时通过构造器传入,如果不指定,默认初始容量=16,加载因子=0.75,加载因子会影响reha...
  • yxinzju
  • yxinzju
  • 2015年08月19日 16:15
  • 832

hashtable、hashmap、ConcurrentHashMap、treemap的区别

本人原创,转载请注明出处! 本人QQ:530422429,欢迎大家指正、讨论。 欢迎访问: 西北工业大学 - 大数据与知识管理研究室 (Northwestern Polytechnical Un...
  • xin_jmail
  • xin_jmail
  • 2014年04月24日 19:51
  • 8561

常用键值对集合解析(HashMap,LinkedHashMap,TreeMap,HashTable,WeakHashMap,SparseArray,Array)

常用键值对集合解析(HashMap,LinkedHashMap,TreeMap,HashTable,WeakHashMap,SparseArray,Array)
  • qq_20280683
  • qq_20280683
  • 2017年03月25日 17:52
  • 422

java中HashMap,LinkedHashMap,TreeMap,HashTable,ConcurrentHashMap的区别和内部实现机制

首先简单介绍下,这几种map的应用场景: HashMap 存储键值对,没有什么特殊的功能; LinkedHashMap在存储的同时,能够保存用户插入数据的顺序,如果需要输出用户插入map的顺序可以...
  • liufangbaishi2014
  • liufangbaishi2014
  • 2016年09月26日 11:44
  • 1743

深入解析HashMap、ConcurrentHashMap丶HashTable丶ArrayList

Java集合类是个非常重要的知识点,HashMap、HashTable、ConcurrentHashMap等算是集合类中的重点,可谓“重中之重”,首先来看个问题,如面试官问你:HashMap和Hash...
  • shadow_zed
  • shadow_zed
  • 2017年10月14日 11:21
  • 88

hashMap,treeMap,LinkedHashMap使用以及区别分析

hashMap,treeMap,LinkedHashMap应用
  • chenpengfei1990
  • chenpengfei1990
  • 2016年11月28日 18:01
  • 711
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:HashMap、TreeMap、Hashtable、LinkedHashMap四者比较
举报原因:
原因补充:

(最多只允许输入30个字)