先来看一下这几个map的关系图
可以看出,Hashtable,HashMap,TreeMap,LinkedHashMap 都是实现与Map借口。不同的是TreeMap实现于 SortedMap,这个就决定了TreeMap存储的数据是可以排序的。
下面用四句话来概括这四个map的用法
1.Hashtable 是安全的(synchronized)
2.LinkedHashMap 保留插入顺序
3.TreeMap 是基于红黑树的数据结构,他的键是有序的
4.HashMap 的键是无序
二 代码
HashMap 用自定义的对象做为键
import java.util.HashMap; import java.util.Map.Entry; public class HashMapTest{ public static void main(String[] args){ HashMap<Person,Integer> hashMap = new HashMap<Person,Integer>(); Person p1 = new Person("Rookie",10); Person p2 = new Person("BruceChen",20); Person p3 = new Person("HackerRookie", 30); Person p4 = new Person("HackerRookie", 30); hashMap.put(p1,10); hashMap.put(p2,20); hashMap.put(p3,30); hashMap.put(p4,30); System.out.println(hashMap.size()); for(Entry entry : hashMap.entrySet()){ System.out.println(entry.getKey().toString() + " - " + entry.getValue()); } } } class Person{ String name ; int age ; public Person(String name,int age){ this.name = name; this.age = age; } public String toString(){ return name + " 年龄 " + age; } }
Output:
4 BruceChen 年龄 20 - 20 Rookie 年龄 10 - 10 HackerRookie 年龄 30 - 30 HackerRookie 年龄 30 - 30
上面的测试类,有一个问题,重复的添加了两个相同的人,HashMap并没有过滤。
要想过滤掉重复的值,需要重写Object对象的 equals() 和hashCode()
class Person{ String name ; int age ; public Person(String name,int age){ this.name = name; this.age = age; } public String toString(){ return name + " 年龄 " + age; } public boolean equals(Object o){ Person p = (Person)o; if(p.name.equals(this.name) && p.age == this.age){ return true; } return (Person)o == this; } public int hashCode(){ return this.name.length(); } }
Output:
3 Rookie 年龄 10 - 10 BruceChen 年龄 20 - 20 HackerRookie 年龄 30 - 30
3. TreeMap
TreeMap的排序是以键来排序的,我们以自定义对象为键来说明
mport java.util.TreeMap; import java.util.Map.Entry; public class TreeMapTest{ public static void main(String[] args){ TreeMap<Duck,Integer> tM = new TreeMap<Duck,Integer>(); Duck d1 = new Duck("white",30); Duck d2 = new Duck("green",10); Duck d3 = new Duck("black",54); tM.put(d1, 10); tM.put(d2,30); tM.put(d3, 40); System.out.println(tM.size()); for(Entry entry : tM.entrySet()){ System.out.println(entry.getKey() + " - " + entry.getValue()); } } } class Duck{ String color; int size; public Duck(String color,int size){ this.color = color; this.size = size; } public boolean equals(Object o){ return ((Duck)o).color == this.color; } public int hashCode(){ return this.color.length(); } public String toString(){ return this.color + " Duck"; } }
Output:(这里抛出异常信息)
Exception in thread "main" java.lang.ClassCastException: com.breeze.test.Duck cannot be cast to java.lang.Comparable at java.util.TreeMap.put(Unknown Source) at com.breeze.test.TreeMapTest.main(TreeMapTest.java:16)
因为TreeMap是以key来来排序的,而我们的Duck对象并没有相互比较的能力.在java中,要想实现比较,必须实现Comparable 借口.在TreeMap中之所以可以用string来做key,就是因为 string实现了comparable借口,现在来修改Duck对象
mport java.util.TreeMap; import java.util.Map.Entry; public class TreeMapTest{ public static void main(String[] args){ TreeMap<Duck,Integer> tM = new TreeMap<Duck,Integer>(); Duck d1 = new Duck("white",30); Duck d2 = new Duck("green",10); Duck d3 = new Duck("black",54); tM.put(d1, 10); tM.put(d2,30); tM.put(d3, 40); System.out.println(tM.size()); for(Entry entry : tM.entrySet()){ System.out.println(entry.getKey() + " - " + entry.getValue()); } } } class Duck implements Comparable<Duck>{ String color; int size; public Duck(String color,int size){ this.color = color; this.size = size; } public boolean equals(Object o){ return ((Duck)o).color == this.color; } public int hashCode(){ return this.color.length(); } public String toString(){ return this.color + " Duck"; } @Override public int compareTo(Duck d){ return d.size - this.size; } }
Output:
3 black Duck - 40 white Duck - 10 green Duck - 30
3.Hasthtable 和 HashMap如出一辙,不同的是,HashMap的值是可以为null的,也不是synchroized
4。LinkedHashMap 继承自HashMap,它使插入linked里的数据,保留插入时的顺序。