java中HashMap的用法

重点介绍HashMap。首先介绍一下什么是Map。在数组中我们是通过数组下标来对其内容索引的,而在Map中我们通过对象来对对象进行索引,用来索引的对象叫做key,其对应的对象叫做value。在下文中会有例子具体说明。

再来看看HashMap和TreeMap有什么区别。HashMap通过hashcode对其内容进行快速查找,而TreeMap中所有的元素都保持着某种固定的顺序,如果你需要得到一个有序的结果你就应该使用TreeMap(HashMap中元素的排列顺序是不固定的)。

 import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Hashtable;
import java.util.TreeMap;
class  HashMaps
{
       public static void main(String[] args)
      {
            Map map=new HashMap();
            map.put("a", "aaa");
            map.put("b", "bbb");
            map.put("c", "ccc");
            map.put("d", "ddd");    

            Iterator iterator = map.keySet().iterator();
            while (iterator.hasNext()) {
             Object key = iterator.next();
             System.out.println("map.get(key) is :"+map.get(key));
            }           

            Hashtable tab=new Hashtable();
            tab.put("a", "aaa");
            tab.put("b", "bbb");
            tab.put("c", "ccc");
            tab.put("d", "ddd");
            Iterator iterator_1 = tab.keySet().iterator();
            while (iterator_1.hasNext()) {
             Object key = iterator_1.next();
             System.out.println("tab.get(key) is :"+tab.get(key));
            }             

            TreeMap tmp=new TreeMap();
            tmp.put("a", "aaa");
            tmp.put("b", "bbb");
            tmp.put("c", "ccc");
            tmp.put("d", "ddd");
            Iterator iterator_2 = tmp.keySet().iterator();
            while (iterator_2.hasNext()) {
             Object key = iterator_2.next();
             System.out.println("tmp.get(key) is :"+tmp.get(key));
            }             

       }    

}

执行完后,果然是这样的(hashmap是没有顺序的,而treemap则是按顺序排列的哦!!)

下面就要进入本文的主题了。先举个例子说明一下怎样使用HashMap:

import java.util.*;     

public class Exp1 {
     public static void main(String[] args){
          HashMap h1=new HashMap();
          Random r1=new Random();
          for(int i=0;i<1000;i++){
               Integer t=new Integer(r1.nextInt(20));
               if(h1.containsKey(t))
                    ((Ctime)h1.get(t)).count++;
               else
                    h1.put(t, new Ctime());
          }
          System.out.println(h1);
     }
}    

class Ctime{
     int count=1;
     public String toString(){
          return Integer.toString(count);
     }
}

在HashMap中通过get()来获取value,通过put()来插入value,ContainsKey()则用来检验对象是否已经存在。可以看出,和ArrayList的操作相比,HashMap除了通过key索引其内容之外,别的方面差异并不大。

前面介绍了,HashMap是基于HashCode的,在所有对象的超类Object中有一个HashCode()方法,但是它和equals方法一样,并不能适用于所有的情况,这样我们就需要重写自己的HashCode()方法。下面就举这样一个例子:

import java.util.*;     

public class Exp2 {
     public static void main(String[] args){
          HashMap h2=new HashMap();
          for(int i=0;i<10;i++)
               h2.put(new Element(i), new Figureout());
          System.out.println("h2:");
          System.out.println("Get the result for Element:");
          Element test=new Element(5);
          if(h2.containsKey(test))
               System.out.println((Figureout)h2.get(test));
          else
               System.out.println("Not found");
     }
}    

class Element{
     int number;
     public Element(int n){
          number=n;
     }
}    

class Figureout{
     Random r=new Random();
     boolean possible=r.nextDouble()>0.5;
     public String toString(){
          if(possible)
               return "OK!";
          else
               return "Impossible!";
     }
}

在这个例子中,Element用来索引对象Figureout,也即Element为key,Figureout为value。在Figureout中随机生成一个浮点数,如果它比0.5大,打印"OK!",否则打印"Impossible!"。之后查看Element(5)对应的Figureout结果如何。

结果却发现,无论你运行多少次,得到的结果都是"Not found"。也就是说索引Element(5)并不在HashMap中。这怎么可能呢?

原因得慢慢来说:Element的HashCode方法继承自Object,而Object中的HashCode方法返回的HashCode对应于当前的地址,也就是说对于不同的对象,即使它们的内容完全相同,用HashCode()返回的值也会不同。这样实际上违背了我们的意图。因为我们在使用HashMap时,希望利用相同内容的对象索引得到相同的目标对象,这就需要HashCode()在此时能够返回相同的值。在上面的例子中,我们期望new Element(i) (i=5)与 Element test=new Element(5)是相同的,而实际上这是两个不同的对象,尽管它们的内容相同,但它们在内存中的地址不同。因此很自然的,上面的程序得不到我们设想的结果。下面对Element类更改如下:

class Element{
     int number;
     public Element(int n){
          number=n;
     }
     public int hashCode(){
          return number;
     }
     public boolean equals(Object o){
          return (o instanceof Element) && (number==((Element)o).number);
     }
}

在这里Element覆盖了Object中的hashCode()和equals()方法。覆盖hashCode()使其以number的值作为hashcode返回,这样对于相同内容的对象来说它们的hashcode也就相同了。而覆盖equals()是为了在HashMap判断两个key是否相等时使结果有意义(有关重写equals()的内容可以参考我的另一篇文章《重新编写Object类中的方法 》)。修改后的程序运行结果如下:

h2:
Get the result for Element:
Impossible!

请记住:如果你想有效的使用HashMap,你就必须重写在其的HashCode()。还有两条重写HashCode()的原则:

不必对每个不同的对象都产生一个唯一的hashcode,只要你的HashCode方法使get()能够得到put()放进去的内容就可以了。即"不为一原则"。 生成hashcode的算法尽量使hashcode的值分散一些,不要很多hashcode都集中在一个范围内,这样有利于提高HashMap的性能。即"分散原则"。

时间: 2024-10-19 08:55:12

java中HashMap的用法的相关文章

java学习笔记——Java中HashMap和TreeMap的区别深入理解

本文转载自Java中HashMap和TreeMap的区别深入理解 首先介绍一下什么是Map.在数组中我们是通过数组下标来对其内容索引的,而在Map中我们通过对象来对对象进行索引,用来索引的对象叫做key,其对应的对象叫做value.这就是我们平时说的键值对. HashMap通过hashcode对其内容进行快速查找,而 TreeMap中所有的元素都保持着某种固定的顺序,如果你需要得到一个有序的结果你就应该使用TreeMap(HashMap中元素的排列顺序是不固定的). HashMap 非线程安全 

【转】 java中HashMap详解

原文网址:http://blog.csdn.net/caihaijiang/article/details/6280251 java中HashMap详解 HashMap 和 HashSet 是 Java Collection Framework 的两个重要成员,其中 HashMap 是 Map 接口的常用实现类,HashSet 是 Set 接口的常用实现类.虽然 HashMap 和 HashSet 实现的接口规范不同,但它们底层的 Hash 存储机制完全一样,甚至 HashSet 本身就采用 H

JAVA中hashmap的分析

从http://blog.csdn.net/luanlouis/article/details/41576373?utm_source=tuicool&utm_medium=referral学习到了java中hashmap的内部原理,非常不错的文章,非常感谢作者的奉献.以下为主要内容摘录. java/scala/c# 语言之中,class 都会含有hashcode,equals之类的方法,这是为什么?数组和链表的区别是什么?在编程开发中应该如何使用?在HashMap内部,采用了数组+链表的形式来

java中stringBuilder的用法

java中stringBuilder的用法 String对象是不可改变的.每次使用 System.String类中的方法之一时,都要在内存中创建一个新的字符串对象,这就需要为该新对象分配新的空间.在需要对字符串执行重复修改的情况下,与创建新的 String对象相关的系统开销可能会非常昂贵.如果要修改字符串而不创建新的对象,则可以使用System.Text.StringBuilder类.例如,当在一个循环中将许多字符串连接在一起时,使用 StringBuilder类可以提升性能. 通过用一个重载的

Java中输入的用法

Java中输入 1. 读取输入 1)构建一个Scanner,附属到System.in Scanner in = new Scanner(System.in); 此时可以使用Scanner类的各种方法来读取输入.例如:nextLine方法来读取一行输入 System.out.print("What is your name?"); String name = in.nextLine(); nextLine():    读取的一行中可能包含空格 next():           读取单个

java中 HashMap和Hashtable,list、set和map 的区别

摘自: http://blog.chinaunix.net/uid-7374279-id-2057584.html HashMap是Hashtable的轻量级实现(非线程安全的实现),他们都完成了Map接口,主要区别在于HashMap允许空(null)键值(key),由于非线程安全,效率上可能高于Hashtable.HashMap允许将null作为一个entry的key或者value,而Hashtable不允许.HashMap把Hashtable的contains方法去掉了,改成contains

Java中List的用法

List接口对Collection进行了简单的扩充. 它的具体实现类常用的有ArrayList和LinkedList. ArrayList从其命名中可以看出它是以一种类似数组的形式存储,因此它的随机访问速度极快,但插入和移除元素的速度很慢. LinkedList的内部实现是链表,它适合于在链表中间需要频繁进行插入和删除操作,不适合随机访问,LinkedList可以当作堆栈.队列和双向队列使用. 一个List可以生成ListIterator,使用它可以从两个方向遍历List,也可以从List中间插

跟王老师学集合(十一)java中Comparator的用法

Java中Comparator的用法 主讲人:王少华  QQ群号:483773664 在java中,如果要对集合对象或数组对象进行排序,需要实现Comparator接口以达到我们想要的目标. 接下来我们模拟下在集合对象中对日期属性进行排序 一.实体类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 package chapter07_11; public class Person {     private int a

Java中HashMap的实现原理

最近面试中被问及Java中HashMap的原理,瞬间无言以对,因此痛定思痛觉得研究一番. 一.Java中的hashCode和equals 1.关于hashCode hashCode的存在主要是用于查找的快捷性,如Hashtable,HashMap等,hashCode是用来在散列存储结构中确定对象的存储地址的 如果两个对象相同,就是适用于equals(java.lang.Object) 方法,那么这两个对象的hashCode一定要相同 如果对象的equals方法被重写,那么对象的hashCode也