`
qlma
  • 浏览: 53673 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

HashMap

阅读更多
遍历HashMap
HashMap attMap;
Iterator i = attMap.entrySet().iterator();
while(i.hasNext()){
    Object o = i.next();
    String key = o.toString();
   //这样就可以遍历该HashMap的key值了。
}
当然也可以遍历Map.Entry项,值。方法类似。


也可以
Object [] obja=attmap.keySet().toArray();

听我们的支持说遍历hashmap使用entryset快些,因大部分都是用keyset遍历的,也没有去想那么多。今天研究了一下,果然差了很多。
见示例,只是简单的hashmap信息。不多说了,大家把这个类在本地运行下,很容易看到结果。

import java.util.HashMap;
import java.util.Iterator;
import java.util.Calendar;

public class HashMapTest {

public static void main(String[] args) {
HashMap hashmap = new HashMap();
for(int i=0;i<1000;i++){
hashmap.put(""+i,"hello");
}

long bs = Calendar.getInstance().getTimeInMillis();
Iterator iterator = hashmap.keySet().iterator();
//String value = "";
while(iterator.hasNext()) {
//value = hashmap.get(iterator.next());
System.out.println(hashmap.get(iterator.next()));
}
System.out.println(Calendar.getInstance().getTimeInMillis() - bs);
listHashMap();
}

public static void listHashMap(){
java.util.HashMap hashmap = new java.util.HashMap();
for(int i=0;i<1000;i++){
hashmap.put(""+i,"hello");
}
long bs = Calendar.getInstance().getTimeInMillis();
//Set set = hashmap.entrySet() ;
java.util.Iterator it = hashmap.entrySet().iterator();
while(it.hasNext()){
java.util.Map.Entry entry = (java.util.Map.Entry)it.next();
// entry.getKey() 返回与此项对应的键
// entry.getValue() 返回与此项对应的值
System.out.println(entry.getValue());
}
System.out.println(Calendar.getInstance().getTimeInMillis() - bs);
}

}

对于keySet其实是遍历了2次,一次是转为iterator,一次就从hashmap中取出key所对于的value。

而entryset只是遍历了第一次,他把key和value都放到了entry中,所以就快了。


对于我们做web的,可能不部分都是用vo对象或是form封装信息,所以用到hashmap时,其内存放的都是上面的对象。因此使用entryset遍历性能会有所提高。

hashmap使用很多,比如导入信息时就要用到,因大部分导入的信息要去判断是否有重复的信息,这样就可以利用containsKey来进行处理了,而不用在插入的时候去进行处理。

HashMap按key排序
HashMap   map   =   new   HashMap();  
         map.put("0201",   "0201");  
         map.put("01",   "01");  
         map.put("0304",   "0304");  
         map.put("0101",   "0101");  

         Object[]   key   =     map.keySet().toArray();  
         Arrays.sort(key);  

         for   (int   i   =   0;   i   <   key.length;   i++)   {  
                 System.out.println(map.get(key[i]));  
         }  


-----------------------------------------------------------------------

Map hashMap = new HashMap();

List arrayList = new ArrayList(hashMap.entrySet());

Collections.sort(arrayList, new Comparator() {
   public int compare(Object o1, Object o2) {
    Map.Entry obj1 = (Map.Entry) o1;
    Map.Entry obj2 = (Map.Entry) o2;
    return (obj1.getKey()).toString().compareTo(obj2.getKey());
   }
  });
//  将HASHMAP中的数据排序-------------------------------------------
  for (Iterator iter = arrayList.iterator(); iter.hasNext();) {
   Map.Entry entry = (Map.Entry) iter.next();
   String     key = (String)entry.getKey();
   ..........
  }
--------------------------------------------------------------------------------------------------------
HashMap可谓JDK的一大实用工具,把各个Object映射起来,实现了“键--值”对应的快速存取。但实际里面做了些什么呢?

  在这之前,先介绍一下负载因子和容量的属性。大家都知道其实一个 HashMap 的实际容量就 因子*容量,其默认值是 16×0.75=12; 这个很重要,对效率很一定影响!当存入HashMap的对象超过这个容量时,HashMap 就会重新构造存取表。这就是一个大问题,我后面慢慢介绍,反正,如果你已经知道你大概要存放多少个对象,最好设为该实际容量的能接受的数字。

  两个关键的方法,put和get:

  先有这样一个概念,HashMap是声明了 Map,Cloneable, Serializable 接口,和继承了 AbstractMap 类,里面的 Iterator 其实主要都是其内部类HashIterator 和其他几个 iterator 类实现,当然还有一个很重要的继承了Map.Entry 的 Entry 内部类,由于大家都有源代码,大家有兴趣可以看看这部分,我主要想说明的是 Entry 内部类。它包含了hash,value,key 和next 这四个属性,很重要。put的源码如下

  public Object put(Object key, Object value) {
  Object k = maskNull(key);

  这个就是判断键值是否为空,并不很深奥,其实如果为空,它会返回一个static Object 作为键值,这就是为什么HashMap允许空键值的原因。

  int hash = hash(k);
  int i = indexFor(hash, table.length);

  这连续的两步就是 HashMap 最牛的地方!研究完我都汗颜了,其中 hash 就是通过 key 这个Object的 hashcode 进行 hash,然后通过 indexFor 获得在Object table的索引值。

  table???不要惊讶,其实HashMap也神不到哪里去,它就是用 table 来放的。最牛的就是用 hash 能正确的返回索引。其中的hash算法,我跟JDK的作者 Doug 联系过,他建议我看看《The art of programing vol3》可恨的是,我之前就一直在找,我都找不到,他这样一提,我就更加急了,可惜口袋空空啊!!!

  不知道大家有没有留意 put 其实是一个有返回的方法,它会把相同键值的 put 覆盖掉并返回旧的值!如下方法彻底说明了 HashMap 的结构,其实就是一个表加上在相应位置的Entry的链表:

  for (Entry e = table[i]; e != null; e = e.next) {
  if (e.hash == hash && eq(k, e.key)) {
  Object oldvalue = e.value;
  e.value = value; //把新的值赋予给对应键值。
  e.recordAccess(this); //空方法,留待实现
  return oldvalue; //返回相同键值的对应的旧的值。
  }
  }
  modCount++; //结构性更改的次数
  addEntry(hash, k, value, i); //添加新元素,关键所在!
  return null; //没有相同的键值返回
  }

  我们把关键的方法拿出来分析:

  void addEntry(int hash, Object key, Object value, int bucketIndex) {
  table[bucketIndex] = new Entry(hash, key, value, table[bucketIndex]);

  因为 hash 的算法有可能令不同的键值有相同的hash码并有相同的table索引,如:key=“33”和key=Object g的hash都是-8901334,那它经过indexfor之后的索引一定都为i,这样在new的时候这个Entry的next就会指向这个原本的table[i],再有下一个也如此,形成一个链表,和put的循环对定e.next获得旧的值。到这里,HashMap的结构,大家也十分明白了吧?
所谓的重构也不神,就是建一个两倍大的table(我在别的论坛上看到有人说是两倍加1,把我骗了),然后再一个个indexfor进去!注意!!这就是效率!!如果你能让你的HashMap不需要重构那么多次,效率会大大提高!

  说到这里也差不多了,get比put简单得多,大家,了解put,get也差不了多少了。对于collections我是认为,它是适合广泛的,当不完全适合特有的,如果大家的程序需要特殊的用途,自己写吧,其实很简单。(作者是这样跟我说的,他还建议我用LinkedHashMap,我看了源码以后发现,LinkHashMap其实就是继承HashMap的,然后override相应的方法,有兴趣的同人,自己looklook)建个 Object table,写相应的算法,就ok啦。

  举个例子吧,像 Vector,list 啊什么的其实都很简单,最多就多了的同步的声明,其实如果要实现像Vector那种,插入,删除不多的,可以用一个Object table来实现,按索引存取,添加等。

  如果插入,删除比较多的,可以建两个Object table,然后每个元素用含有next结构的,一个table存,如果要插入到i,但是i已经有元素,用next连起来,然后size++,并在另一个table记录其位置。
---------------------------------------------------------------------------------------------------------------------------------------------------------
Hashtable和HashMap的区别:
1.Hashtable是Dictionary的子类,HashMap是Map接口的一个实现类;
2.Hashtable中的方法是同步的,而HashMap中的方法在缺省情况下是非同步的。即是说,在多线程应用程序中,不用专门的操作就安全地可以使用Hashtable了;而对于HashMap,则需要额外的同步机制。但HashMap的同步问题可通过Collections的一个静态方法得到解决:
Map Collections.synchronizedMap(Map m)
这个方法返回一个同步的Map,这个Map封装了底层的HashMap的所有方法,使得底层的HashMap即使是在多线程的环境中也是安全的。
3.在HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。当get()方法返回null值时,即可以表示HashMap中没有该键,也可以表示该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键,而应该用containsKey()方法来判断。
---------------------------------------------------------------------------------------------------------------------------------------------------------

下面的部分,我们将展示两个实例,第一个展示了HashMap的使用,第二个则使用了TreeMap。注意代码中的唯一差别仅在一行而已,位于calendar Map实例化时,然而,由于TreeMap和HashMap的存储行为的不同,最终的输出就大不相同了。

4.1 HashMap 实例
import java.util.*;
public class ExampleHashMap {
   //calendar Map 
   Map calendar = new  HashMap();
   //constructor to add all elements into Map
   public ExampleHashMap(String d[], String i[]){
      for (int x=0; x<d.length; x++)
         calendar.put(d[x], i[x]);
   }
   //main method
   public static void main(String args[]) {
      //Data to be inserted into calendar
      String [] dates = {"10/31/01", "01/01/01", "03/05/01", "02/04/01"};
      String [] items = {"Halloween", "New Years", "Birthday", "Anniversary"};
      //create instance of class
      ExampleHashMap example = new ExampleHashMap(dates, items);
      //print out all key/value pairs in map
      System.out.println("map= " + example.calendar);
      //retrieve mappings into Set
      Set mappings = example.calendar.entrySet();
      System.out.println("object \t\t\tkey\t\tvalue");
      //iterate through mappings and print content
      for (Iterator i = mappings.iterator(); i.hasNext();) {
         Map.Entry me = (Map.Entry)i.next();
         Object ok = me.getKey();
         Object ov = me.getValue();
         System.out.print(me + "\t");
         System.out.print(ok + "\t");
         System.out.println(ov); 
      }
   }
}


- HashMap的输出 (不同的编译器会有不同顺序的输出):
[pre]/tmp> java ExampleHashMap
map= {01/01/01=New Years, 03/05/01=Birthday, 02/04/01=Anniversary, 10/31/01=Halloween}
object                  key             value
01/01/01=New Years      01/01/01        New Years
03/05/01=Birthday       03/05/01        Birthday
02/04/01=Anniversary    02/04/01        Anniversary
10/31/01=Halloween      10/31/01        Halloween[/pre]
注意在HashMap对象存储既不是按照年代顺序,也不是按照字母顺序。输出的顺序其实是依赖于你选用了哪种编译器,以及机器的设置。实际上Halloween是第一个“put”到HashMap的,但是却存储在HashMap的最后。

4.2 TreeMap 实例
import java.util.*;
public class ExampleTreeMap {
   //calendar Map 
   Map calendar = new TreeMap();
   //constructor to add all elements into Map
   public ExampleTreeMap(String d[], String i[]){
      for (int x=0; x<d.length; x++)
         calendar.put(d[x], i[x]);
   }
   //main method
   public static void main(String args[]) {
      //Data to be inserted into calendar
      String [] dates = {"10/31/01", "01/01/01", "03/05/01", "02/04/01"};
      String [] items = {"Halloween", "New Years", "Birthday", "Anniversary"};
      //create instance of class
      ExampleTreeMap example = new ExampleTreeMap(dates, items);
      //print out all key/value pairs in map
      System.out.println("map= " + example.calendar);
      //retrieve mappings into Set
      Set mappings = example.calendar.entrySet();
      System.out.println("object \t\t\tkey\t\tvalue");
      //iterate through mappings and print content
      for (Iterator i = mappings.iterator(); i.hasNext();) {
         Map.Entry me = (Map.Entry)i.next();
         Object ok = me.getKey();
         Object ov = me.getValue();
         System.out.print(me + "\t");
         System.out.print(ok + "\t");
         System.out.println(ov); 
      }
   }
}

- TreeMap的输出:
[pre]/tmp> java ExampleTreeMap
map= {01/01/01=New Years, 02/04/01=Anniversary, 03/05/01=Birthday, 10/31/01=Halloween}
object                  key             value
01/01/01=New Years      01/01/01        New Years
02/04/01=Anniversary    02/04/01        Anniversary
03/05/01=Birthday       03/05/01        Birthday
10/31/01=Halloween      10/31/01        Halloween[/pre]

TreeMap的输出比HashMap更加具有可预言性。注意在TreeMap中映射以关键字的字母顺序存储。不同于HashMap的输出,在一个实际的世界日历程序中,TreeMap的输出将更加有用。正如前面提及的,使用TreeMap数据结构的一个缺点是,当你在TreeMap结构中“put”或“remove”元素时,因为需要排序从而需要一些开销,这会影响到程序的性能。(译注:可以先使用HashMap,在需要顺序输出时,通过把HashMap对象作为参数传入,构造一个TreeMap达到高性能同时满足排序的双重目的)。

分享到:
评论

相关推荐

    HashMap之resize()方法源码解读.docx

    HashMap之resize()方法源码解读 HashMap的resize()方法是HashMap中最核心的方法之一,该方法负责扩容HashMap的容量,以便存储更多的键值对。下面我们将对HashMap的resize()方法进行源码解读,了解其扩容机制和原理...

    hashmap面试题_hashmap_

    《HashMap面试题详解》 HashMap作为Java集合框架中的重要成员,是面试中常见的知识点,尤其在数据结构与算法、并发编程以及JVM内存管理等领域,HashMap的深入理解至关重要。本篇将围绕HashMap的相关面试题,从基础...

    hashMap和hashTable的区别

    ### hashMap和hashTable的区别 #### 一、简介与基本概念 `HashMap` 和 `HashTable` 都是 Java 集合框架中非常重要的数据结构,它们都实现了 `Map` 接口,用于存储键值对。尽管它们在功能上有很多相似之处,但在...

    关于如何解决HashMap线程安全问题的介绍

    在Java编程中,HashMap是一个非常常用的集合类,用于存储键值对数据。然而,它存在一个重要的特性,那就是线程不安全。理解这个问题并找到解决方案是每个Java开发者必须掌握的知识。 HashMap线程不安全的原因主要...

    HashMap和HashTable的区别和不同

    ### HashMap与HashTable的区别详解 #### 引言 在Java编程中,`HashMap`与`HashTable`作为两种常用的数据结构,经常被用来存储键值对数据。尽管它们在功能上相似,但在实现细节、性能表现以及使用场景方面存在显著...

    HashMap介绍和使用

    ### HashMap介绍和使用详解 #### 一、HashMap的数据结构 HashMap是Java集合框架的一个重要组成部分,它实现了Map接口,能够存储键值对映射。在Java编程语言中,最基本的数据结构有两种:数组和引用(模拟指针)。...

    JNI处理hashmap,string等对象的操作

    在这个主题中,我们将深入探讨如何使用JNI处理HashMap、String等对象。 首先,让我们来理解JNI的基本结构。JNI接口提供了大量的函数,让本地方法(C/C++代码)能够创建、访问和修改Java对象。要使用JNI,你需要定义...

    用HashMap模拟一个网上购物车

    ### 使用HashMap模拟网上购物车 #### 一、项目背景与目标 在本实验中,我们通过使用Java语言中的`HashMap`来模拟一个简单的网上购物车系统。该项目的主要目的是熟悉Java集合框架中的`HashMap`类,并了解如何利用它...

    HashMap的数据结构

    HashMap是Java编程语言中一个非常重要的数据结构,它属于集合框架的一部分,主要用于存储键值对(Key-Value)数据。HashMap在内部实现上基于哈希表,也称为散列表,它提供了一种快速查找、插入和删除数据的方法,...

    ibatis 用HashMap解决resultClass映射

    ### ibatis 使用 HashMap 解决 resultClass 映射 在日常的软件开发过程中,尤其是在处理数据库查询时,我们经常面临一个问题:如何优雅地处理那些未知或动态变化的列名及列数的情况?在这种情况下,传统的实体类...

    Java HashMap类详解

    Java HashMap 类详解 本资源详细介绍了 Java 中的 HashMap 类,包括其实现机制、Hash 存储机制、集合存储机制等方面的知识点。 1. HashMap 和 HashSet 的关系 HashMap 和 HashSet 是 Java Collection Framework ...

    Java中HashMap详解(通俗易懂).doc

    Java中的HashMap是一个非常重要的数据结构,它实现了Map接口,提供了键值对的高效存储和访问。HashMap基于哈希表(也称为散列表)原理工作,它允许用户通过键(Key)快速查找对应的值(Value)。在HashMap中,键和值...

    hashmap实现原理

    哈希映射(HashMap)是Java编程语言中广泛使用的数据结构之一,主要提供键值对的存储和查找功能。HashMap的实现基于哈希表的概念,它通过计算对象的哈希码来快速定位数据,从而实现了O(1)的平均时间复杂度。在深入...

    HashMap类.rar

    HashMap类在Java编程语言中是集合框架的一部分,它是一个基于哈希表的Map接口实现。HashMap提供了快速的插入、删除和查找操作,平均时间复杂度为O(1)。在这个压缩包“HashMap类.rar”中,包含的是易语言版本的...

    java中HashMap,LinkedHashMap,TreeMap,HashTable的区别

    ### Java中HashMap, LinkedHashMap, TreeMap,HashTable的区别 在Java编程语言中,`Map`接口是集合框架中的一个重要组成部分,用于存储键值对。本文将详细分析四种常用的`Map`实现类:`HashMap`, `LinkedHashMap`, ...

    HASHMAP排序功能描述

    HashMap是Java编程语言中常用的集合类之一,它属于哈希表数据结构,提供key-value的存储方式,并且具有快速查询的特性。然而,HashMap本身并不保证元素的顺序,特别是当涉及到遍历或输出HashMap的内容时,顺序可能会...

    简单的key value hashmap

    哈希映射(HashMap)是Java编程语言中一个非常重要的数据结构,它在《简单的key value hashmap》中被提及,通常用于存储键值对(key-value pairs)。HashMap是Java集合框架的一部分,它提供了高效的查找、插入和删除...

    马士兵老师HashMap学习笔记

    《马士兵老师HashMap学习笔记详解》 HashMap是Java编程语言中常用的一种数据结构,它提供了键值对(key-value pair)的存储功能,是基于哈希表实现的。马士兵老师的HashMap学习笔记深入剖析了这一核心组件的工作...

    一个delphi的hashmap源代码

    在IT行业中,哈希表(HashMap)是一种高效的数据结构,它使用哈希函数将键(Key)映射到数组的特定位置,以便快速存取数据。Delphi是一种强大的Object Pascal编程语言,它提供了多种实现哈希表的方式。在这个特定的...

Global site tag (gtag.js) - Google Analytics