先来看一下这几个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里的数据,保留插入时的顺序。