Java 集合系列10之 HashMap详细介绍(源码解析)和使用示例

转自:http://www.cnblogs.com/skywang12345/p/3310835.html

第一部分 HashMap介绍

HashMap简介

  1. HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。
  2. HashMap 继承于AbstractMap,实现了Map、Cloneable、java.io.Serializable接口。
  3. HashMap的实现不是同步的,这意味着它不是线程安全的。它的key、value都可以为null。此外,HashMap中的映射不是有序的。
  4. HashMap 的实例有两个参数影响其性能:“初始容量” 和 “加载因子”。容量 是哈希表中桶的数量,初始容量 只是哈希表在创建时的容量。加载因子 是哈希表在其容量自动增加之前可以达到多满的一种尺度。当哈希表中的条目数超出了加载因子与当前容量的乘积时,则要对该哈希表进行 rehash 操作(即重建内部数据结构),从而哈希表将具有大约两倍的桶数。
  5. 通常,默认加载因子是 0.75这是在时间和空间成本上寻求一种折衷。加载因子过高虽然减少了空间开销,但同时也增加了查询成本(在大多数 HashMap 类的操作中,包括 get 和 put 操作,都反映了这一点)。在设置初始容量时应该考虑到映射中所需的条目数及其加载因子,以便最大限度地减少 rehash 操作次数。如果初始容量大于最大条目数除以加载因子,则不会发生 rehash 操作。

HashMap构造函数

HashMap()                // 构造一个空的 HashMap ,默认初始容量(16)和默认负载因子(0.75)。 

HashMap(int capacity)    // 指定“容量大小”的构造函数

HashMap(int capacity, float loadFactor)    // 指定“容量大小”和“加载因子”的构造函数

HashMap(Map<? extends K, ? extends V> map) // 包含“子Map”的构造函数

HashMap API

void                 clear()                    //从Map中删除所有的映射
Object               clone()                    //返回此 HashMap实例的浅拷贝:键和值本身不被克隆
boolean              containsKey(Object key)    //如果此映射包含指定键的映射关系,则返回true
boolean              containsValue(Object value)//如果此映射将一个或多个键映射到指定值,则返回true
Set<Entry<K, V>>     entrySet()                 //返回此映射中包含的映射的Set视图
V                    get(Object key)            //返回指定键映射到的值;如果此映射不包含键映射,则返回null
boolean              isEmpty()                  //如果此映射不包含键-值映射,则返回true
Set<K>               keySet()                   //返回此映射中包含的键的Set视图。
V                    put(K key, V value)        //将指定的值与此映射中指定的键关联
void                 putAll(Map<? extends K, ? extends V> map)//将指定Map中的所有映射复制到此Map
V                    remove(Object key)         //如果存在,则从该映射中删除指定键的映射
int                  size()                     //返回此映射中键 - 值映射的数量
Collection<V>        values()                   //返回此映射中包含的值的集合视图。

第二部分 HashMap数据结构

HashMap 的继承关系
java.lang.Object
   ↳ java.util.AbstractMap<K, V>
         ↳ java.util.HashMap<K, V>

public class HashMap<K,V>
    extends AbstractMap<K,V>
    implements Map<K,V>, Cloneable, Serializable { }

HashMap 和Map的关系图


从图中可以看出: 

  1. HashMap继承于AbstractMap类,实现了Map接口。Map是"key-value键值对"接口,AbstractMap实现了"键值对"的通用函数接口。 
  2. HashMap是通过"拉链法"实现的哈希表。它包括几个重要的成员变量:table, size, threshold, loadFactor, modCount
  • table:是一个Entry[]数组类型,而Entry实际上就是一个单向链表。哈希表的"key-value键值对"都是存储在Entry数组中的。 
  • size:是HashMap的大小,它是HashMap保存的键值对的数量。 
  • threshold:是HashMap的阈值,用于判断是否需要调整HashMap的容量。threshold的值="容量*加载因子",当HashMap中存储数据的数量达到threshold时,就需要将HashMap的容量加倍。loadFactor:就是加载因子。 
  • modCount:是用来实现fail-fast机制的。

第三部分 HashMap遍历方式

扫描二维码关注公众号,回复: 142803 查看本文章

1.遍历HashMap的键值对

第一步: 根据entrySet()获取HashMap的“键值对”的Set集合。

第二步:通过Iterator迭代器遍历“第一步”得到的集合。

// 假设map是HashMap对象
// map中的key是String类型,value是Integer类型
Integer intege = null;
Iterator iter = map.entrySet().iterator();
while(iter.hasNext()) {
    Map.Entry entry = (Map.Entry)iter.next();
    // 获取key
    key = (String)entry.getKey();
    // 获取value
    integ = (Integer)entry.getValue();
}

2.遍历HashMap 的键

第一步:根据value()获取HashMap的“值”的集合。

第二步:通过Iterator迭代器遍历“第一步”得到的集合。

// 假设map是HashMap对象
// map中的key是String类型,value是Integer类型
Integer value = null;
Collection c = map.values();
Iterator iter= c.iterator();
while (iter.hasNext()) {
    value = (Integer)iter.next();
}

3. 遍历测试程序

import java.util.Map;
import java.util.Random;
import java.util.Iterator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map.Entry;
import java.util.Collection;

/*
 * @desc 遍历HashMap的测试程序。
 *   (1) 通过entrySet()去遍历key、value,参考实现函数:
 *        iteratorHashMapByEntryset()
 *   (2) 通过keySet()去遍历key、value,参考实现函数:
 *        iteratorHashMapByKeyset()
 *   (3) 通过values()去遍历value,参考实现函数:
 *        iteratorHashMapJustValues()
 *
 * @author skywang
 */
public class HashMapIteratorTest {

    public static void main(String[] args) {
        int val = 0;
        String key = null;
        Integer value = null;
        Random r = new Random();
        HashMap map = new HashMap();

        for (int i=0; i<12; i++) {
            // 随机获取一个[0,100)之间的数字
            val = r.nextInt(100);
            
            key = String.valueOf(val);
            value = r.nextInt(5);
            // 添加到HashMap中
            map.put(key, value);
            System.out.println(" key:"+key+" value:"+value);
        }
        // 通过entrySet()遍历HashMap的key-value
        iteratorHashMapByEntryset(map) ;
        
        // 通过keySet()遍历HashMap的key-value
        iteratorHashMapByKeyset(map) ;
        
        // 单单遍历HashMap的value
        iteratorHashMapJustValues(map);        
    }
    
    /*
     * 通过entry set遍历HashMap
     * 效率高!
     */
    private static void iteratorHashMapByEntryset(HashMap map) {
        if (map == null)
            return ;

        System.out.println("\niterator HashMap By entryset");
        String key = null;
        Integer integ = null;
        Iterator iter = map.entrySet().iterator();
        while(iter.hasNext()) {
            Map.Entry entry = (Map.Entry)iter.next();
            
            key = (String)entry.getKey();
            integ = (Integer)entry.getValue();
            System.out.println(key+" -- "+integ.intValue());
        }
    }

    /*
     * 通过keyset来遍历HashMap
     * 效率低!
     */
    private static void iteratorHashMapByKeyset(HashMap map) {
        if (map == null)
            return ;

        System.out.println("\niterator HashMap By keyset");
        String key = null;
        Integer integ = null;
        Iterator iter = map.keySet().iterator();
        while (iter.hasNext()) {
            key = (String)iter.next();
            integ = (Integer)map.get(key);
            System.out.println(key+" -- "+integ.intValue());
        }
    }
    

    /*
     * 遍历HashMap的values
     */
    private static void iteratorHashMapJustValues(HashMap map) {
        if (map == null)
            return ;
        
        Collection c = map.values();
        Iterator iter= c.iterator();
        while (iter.hasNext()) {
            System.out.println(iter.next());
       }
    }
}

第四部分 HashMap示例

import java.util.Map;
import java.util.Random;
import java.util.Iterator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map.Entry;
import java.util.Collection;

/*
 * @desc HashMap测试程序
 *        
 * @author skywang
 */
public class HashMapTest {

    public static void main(String[] args) {
        testHashMapAPIs();
    }
    
    private static void testHashMapAPIs() {
        // 初始化随机种子
        Random r = new Random();
        // 新建HashMap
        HashMap map = new HashMap();
        // 添加操作
        map.put("one", r.nextInt(10));
        map.put("two", r.nextInt(10));
        map.put("three", r.nextInt(10));

        // 打印出map
        System.out.println("map:"+map );

        // 通过Iterator遍历key-value
        Iterator iter = map.entrySet().iterator();
        while(iter.hasNext()) {
            Map.Entry entry = (Map.Entry)iter.next();
            System.out.println("next : "+ entry.getKey() +" - "+entry.getValue());
        }

        // HashMap的键值对个数        
        System.out.println("size:"+map.size());

        // containsKey(Object key) :是否包含键key
        System.out.println("contains key two : "+map.containsKey("two"));
        System.out.println("contains key five : "+map.containsKey("five"));

        // containsValue(Object value) :是否包含值value
        System.out.println("contains value 0 : "+map.containsValue(new Integer(0)));

        // remove(Object key) : 删除键key对应的键值对
        map.remove("three");

        System.out.println("map:"+map );

        // clear() : 清空HashMap
        map.clear();

        // isEmpty() : HashMap是否为空
        System.out.println((map.isEmpty()?"map is empty":"map is not empty") );
    }
}

运行一次结果如下:

map:{two=7, one=9, three=6}
next : two - 7
next : one - 9
next : three - 6
size:3
contains key two : true
contains key five : false
contains value 0 : false
map:{two=7, one=9}
map is empty


猜你喜欢

转载自blog.csdn.net/wh43023/article/details/80209317