JavaSE入门学习37:Java集合框架之Map接口及其实现类HashMap和TreeMap

来源:互联网 发布:凸优化求解python库 编辑:程序博客网 时间:2024/05/17 06:46

        一Map接口

        Map接口中的每个成员方法由一个关键字(key)和一个值(value)构成。Map接口不直接继承于Collection接口,因

为它包装的是一组成对的"键-值"对象的集合,而且在Map接口的集合中也不能有重复的key出现,因为每个键只能与

一个成员元素相对应。

        Map接口定义了存储"键(key)——值(value)映射对"的方法。实现Map接口的类用来存储键值对。Map接口中包含

了一个keySet()方法,用于返回Map中所有key组成的Set集合。

        Map接口的特点有: 

        1)Map接口提供了一种映射关系,其中的元素是以键值对(key-value)的形式存储的,能够实现根据key快速查找value。

        2)Map中的键值对以Entry类型的对象实例形式存在。键(key值)不可重复,value值可以。

        3)每个键最多只能映射到一个值。

        4)Map接口提供了分别返回key值集合,value值集合以及Entry(键值对)集合的方法。

        5)Map同样也支持泛型,形式如:Map<K,V>。

        6)Map接口中存储的键—值对通过键来标识,所以键值不能重复,即同一个Map对象的任何两个key通过equals()

方法比较总是返回false。

       Map接口中定义的方法有:


       Map接口的主要有三个实现类,分别是:HashMap、TreeMap和HashTable。一般情况下,我们用的最多的是

HashMap,在Map中插入、删除和定位元素,HashMap是最好的选择。但如果您要按自然顺序或自定义顺序遍历

键,那么TreeMap会更好。如果需要输出的顺序和输入的相同。那么用HashMap的子类LinkedHashMap可以实现,

它还可以按读取顺序来排列。

        二HashMap实现类

        Hashmap类是一个最常用的Map,它根据键的HashCode值存储数据,根据键可以直接获取它的值,具有很快的访

速度,遍历时,取得数据的顺序是完全随机的。HashMap最多只允许一条记录的键为Null;允许多条记录的值为

 Null;HashMap不支持线程的同步,即任一时刻可以有多个线程同时写HashMap;可能会导致数据的不一致。如果需要

同步,可以用Collections集合类的synchronizedMap()方法使HashMap类具有同步的能力。

        由于HashMap里的不能重复,所以HashMap里最多只有一对key-value值为null,但可以有无数多项key-value对

的value为null。

  HashMap重写了toString()方法方法总是返回如下格式的字符串:{key1 = value1,key2 = value2...}

  HashMap判断两个key相等的标准是:两个key通过equasl()方法比较返回ture,两个key的hashCode值相等。

       HashMap的特点:

       1)HashMap是Map的一个重要实现类,也是最常用的,基于哈希表实现。

       2)HashMap中的Entry对象是无序排列的。

       3)Key值和value值都可以是null,但是一个HashMap只能有一个key值为null的映射(key值不可重复)。

       HashMap实现类的方法:


       实例:

import java.util.*;public class TestHashMap {public static void main(String[] args) {Map<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 sizeSystem.out.println(hashMap.size()); //loop HashMapfor (Map.Entry<Dog, Integer> entry : hashMap.entrySet()) {System.out.println(entry.getKey().toString() + " - " + entry.getValue());}}}class Dog {String color; Dog(String c) {color = c;}public String toString(){return color + " dog";}}

      运行结果:


      注意看,我们错误地添加了两次"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";    }}

      运行结果:


      原因在于HashMap不运行两个相同的元素作为KEY。如果没有重写,使用的就会是Object类实现的hashCode()和

equals()方法,默认的 hashCode()方法实现对每个不同的对象返回不同的整数;默认的equals()方法只比较两个引用

是否指向同一个实际对象。

      三TreeMap实现类

      Map接口派生了一个SortedMap子接口,TreeMap为其实现类。类似TreeSet排序,TreeMap也是基于红黑树对

TreeMap中所有key进行排序,从而保证TreeMap中所有key-value对处于有序状态。TreeMap两种排序方法:

       1)自然排序:TreeMap的所有key必须实现Comparable接口,而且所有key应该是同一个类的对象,否则将会抛出

ClassCastExcepiton异常。

       2)定制排序:创建TreeMap时,传入一个Comparator对象,该对象负责对TreeMap中所有key进行排序。采用定

制排序时不要求Map的key实现Comparable接口。

  TreeMap中判断两个key相等的标准也是两个key通过equals()方法比较返回true,而通过compareTo()方法返回

0,TreeMap即认为这两个key是相等的。

  如果使用自定义的类作为TreeMap的key,应重新该类的equals(0方法和compareTo()方法时应有一致的返回结

果:即两个key通过equals()方法比较返回true时,它们通过compareTo()方法比较应该返回0。如果equals()方法与

compareTo()方法的返回结果不一致,要么该TreeMap与Map接口的规则有出入(当equals()方法比较返回true,但

CompareTo()方法比较不返回0时),要么TreeMap处理起来性能有所下降(当compareTo()方法比较返回0,当

equals()方法比较不返回true时)。

         TreeMap实现了的方法:




        实例:

import java.util.*;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"); Map<Dog, Integer> treeMap = new TreeMap<Dog, Integer>();treeMap.put(d1, 10);treeMap.put(d2, 15);treeMap.put(d3, 5);treeMap.put(d4, 20); for (Map.Entry<Dog, Integer> entry : treeMap.entrySet()) {System.out.println(entry.getKey() + " - " + entry.getValue());}}}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";}}

        运行结果:


       既然TreeMap是按key排序的,那么key对象就必须可以和另一个对象作比较,因此必须实现Comparable接口。当

然,你也可以使用String对象作为key,因为String类已经实现了Comparable接口。

       下面,我们修改Dog类的代码,使其实现Comparable接口:

import java.util.*;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); Map<Dog, Integer> treeMap = new TreeMap<Dog, Integer>();treeMap.put(d1, 10);treeMap.put(d2, 15);treeMap.put(d3, 5);treeMap.put(d4, 20); for (Map.Entry<Dog, Integer> entry : treeMap.entrySet()) {System.out.println(entry.getKey() + " - " + entry.getValue());}}}class Dog implements Comparable<Dog>{String color;int size; Dog(String c, int s) {color = c;size = s;} public String toString(){return color + " dog";} @Overridepublic int compareTo(Dog o) {return  o.size - this.size;}}

       运行结果:


       这就是根据key对象排序的结果,此处我们使用了size(尺寸)来比较dog.如果我们把"Dog d4 = new Dog("white"

,10);"这一行代码替换为"Dog d4 = new Dog("white", 40);"那么,执行后的结果为:


       原因是TreeMap使用compareTo()方法来比较key对象,不同的size就被认为是不同的dog。

       关于Map接口及其实现类的东西就说这么多。

      

1 0