map是java中最常用的数据结构之一,在这篇文中,我将说明如何使用不同类型的maps,比如:HashMap,TreeMap,HashTable和LinkedHashMap。
Map概览
在java SE 中有4个Map常用的实现,分别是HashMap,TreeMap,HashTable和LinkedHashMap。用一句话来描述这四个实分别是:
HashMap是hash table的一个实现,它中的键值是无序的。
TreeMap是基于红黑树结构的一个实现,它是根据key来排序的。
LinkedHashMap保留了插入的顺序。
HashTabe是同步的,与HashMap相比,它有个同步的开销,因此如果程序是线程安全的,那么HashMap是个不错的选择。
HasMap
如果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都接受了,这并没有意义,因为现在很疑惑到底有多少个白狗
对Dog类的定义应该如下:
class Dog { String color; Dog(String c) { color = c; } public boolean equals(Object o) { return ((Dog) o).color.equals(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不允许有两个相同的元素,默认情况下,hashcode()和equals()方法在对象的实现时使用,默认hashcode()方法给不同对象不同的整数,equals()方法只有在两个引用指向同一对象时才会返回true。
TreeMap
TreeMap是根据key进行排序的,让我们先来看看下边这个例子来理解什么事根据key排序
class Dog { String color; Dog(String c) { color = c; } public boolean equals(Object o) { return ((Dog) o).color.equals(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)
因为TreeMaps是根据key来排序的,这个对象key必须能够互相比较,这就是为什么Dog要实现Comparable接口。例如,你利用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的大小,
如果Dog d4 = new Dog("white",10),被替代为Dog d4 = new Dog("white", 40);输出结果则是
white dog - 20 red dog - 10 black dog - 15 white dog - 5
Hashtable
来自java DOC的解释:
HashMap类大致相当于Hashtable,除了它是不同步的和允许是空值的之外。
LisnkedHashMap
LinkedHashMap是HashMap的子类,这意味着 它集成了HashMap的特点,除此之外,LinkedHashMap保留了插入时的顺序。让我们用LinkedHashMap代替HashMap,来看看刚才代码的实现:
class Dog { String color; Dog(String c) { color = c; } public boolean equals(Object o) { return ((Dog) o).color.equals(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不同的是,HashMap的插入顺序是没有被保持的。
red dog - 10 white dog - 20 black dog - 15
//下边是自己加的判断为空的情况
map == null 是指没有引用的对象。
map.size() == 0 指map中没有元素。是一个空的集合。
要判断map是空的。要先判断是不是null 再看size。
map.size() == 0 指map中没有元素。是一个空的集合。
要判断map是空的。要先判断是不是null 再看size。