zoukankan      html  css  js  c++  java
  • HashSet与HashMap、Hashtable

    (最近在老师叫我们用java去实现LRU算法,了解到要用双链表去做,要用到LinkHashMap去做,但自己对java的几大集合框架并不熟悉,在学习过程了解到了HashMap和HashSet,做个简单笔记吧)

    HashMap

    HashMap是一个有序的集合,是有一对属性值的集合,属性包含key,和value。关键字key是唯一不重复的,查询起来速度很快。

    HashMap 的实例有两个参数影响其性能:初始容量 加载因子。容量是 哈希表中桶的数量,初始容量只是哈希表在创建时的容量。加载因子 是哈希表在其容量自动增加之前可以达到多满的一种尺度。当哈希表中的条目数超出了加载因子与当前容量的乘积时,通过调用 rehash 方法将容量翻倍。 
    通常,默认加载因子 (.75) 在时间和空间成本上寻求一种折衷。加载因子过高虽然减少了空间开销,但同时也增加了查询成本(在大多数 HashMap 类的操作中,包括 get 和 put 操作,都反映了这一点)。在设置初始容量时应该考虑到映射中所需的条目数及其加载因子,以便最大限度地降低 rehash 操作次数。如果初始容量大于最大条目数除以加载因子,则不会发生 rehash 操作。

    HashSet

    而HashSet(散列表)就像是把HashMap中value去掉,说白了就是只有一个key的HashMap集合。它实现了Set接口,意味着它的元素不能有重复值出现。HashSet中有add、remove、contains 和 size方法,没有get()方法,但可以通过iterator()来实现,迭代所需的时间与 HashSet 实例的大小(元素的数量)成比例。且对于 HashSet 而言,它是基于 HashMap 实现的。

    下面是HashSet的源代码:

    public class HashSet<E> extends AbstractSet<E> 
         implements Set<E>, Cloneable, java.io.Serializable 
     { 
         // 使用 HashMap 的 key 保存 HashSet 中所有元素
         private transient HashMap<E,Object> map; 
         // 定义一个虚拟的 Object 对象作为 HashMap 的 value 
         private static final Object PRESENT = new Object(); 
         ... 
         // 初始化 HashSet,底层会初始化一个 HashMap 
         public HashSet() 
         { 
             map = new HashMap<E,Object>(); 
         } 
         // 以指定的 initialCapacity、loadFactor 创建 HashSet 
         // 其实就是以相应的参数创建 HashMap 
         public HashSet(int initialCapacity, float loadFactor) 
         { 
             map = new HashMap<E,Object>(initialCapacity, loadFactor); 
         } 
         public HashSet(int initialCapacity) 
         { 
             map = new HashMap<E,Object>(initialCapacity); 
         } 
         HashSet(int initialCapacity, float loadFactor, boolean dummy) 
         { 
             map = new LinkedHashMap<E,Object>(initialCapacity 
                 , loadFactor); 
         } 
         // 调用 map 的 keySet 来返回所有的 key 
         public Iterator<E> iterator() 
         { 
             return map.keySet().iterator(); 
         } 
         // 调用 HashMap 的 size() 方法返回 Entry 的数量,就得到该 Set 里元素的个数
         public int size() 
         { 
             return map.size(); 
         } 
         // 调用 HashMap 的 isEmpty() 判断该 HashSet 是否为空,
         // 当 HashMap 为空时,对应的 HashSet 也为空
         public boolean isEmpty() 
         { 
             return map.isEmpty(); 
         } 
         // 调用 HashMap 的 containsKey 判断是否包含指定 key 
         //HashSet 的所有元素就是通过 HashMap 的 key 来保存的
         public boolean contains(Object o) 
         { 
             return map.containsKey(o); 
         } 
         // 将指定元素放入 HashSet 中,也就是将该元素作为 key 放入 HashMap 
         public boolean add(E e) 
         { 
             return map.put(e, PRESENT) == null; 
         } 
         // 调用 HashMap 的 remove 方法删除指定 Entry,也就删除了 HashSet 中对应的元素
         public boolean remove(Object o) 
         { 
             return map.remove(o)==PRESENT; 
         } 
         // 调用 Map 的 clear 方法清空所有 Entry,也就清空了 HashSet 中所有元素
         public void clear() 
         { 
             map.clear(); 
         } 
         ... 
     }

    Hashtable

    另外还有Hashtable ,网上说这三个的区别在面试时经常会遇到,呵呵,但到现在好像很少遇到Hashtable,是因为HashMap是新框架中用来代替HashTable的类么?Hashtable是Dictionary的子类,方法是同步的,不允许null值(key和value都不可以),而HashMa是Map接口的一个实现类,方法是异步的,允许null值出现。

    一些简单的测试程序,摘下了,便于理解:

    public static void main(String[] args) {
      Hashtable<Integer, String> table = new Hashtable<Integer, String>();
      table.put(1, "1");
      //table.put(2, null);   //Hashtable 不允许null值 有null就会报异常
      
    for(int i=0;i<table.size();i++){
       System.out.println(table.get(1));
      }
      System.out.println("#############");
      HashMap<Integer, String> map = new HashMap<Integer, String>();
      map.put(1, "2");
      map.put(2, "3");
      map.put(null,null);      //HashMap 允许null值,但key只能有一个null,否则后面不会被保存,
      for(int i=0;i<map.size();i++){
       System.out.println(map.get(1));
      }
      
      System.out.println("#############");
    //HashSet  值不能重复  无序的不能用get()来取对象
      HashSet<Integer> s = new HashSet<Integer>();
      s.add(Integer.valueOf(1));
      s.add(Integer.valueOf(1));
      for(Integer i:s){
       System.out.println(i);
      }
     }

    (代码源于http://blog.sina.com.cn/s/blog_4586764e0100ivup.html

    google搜索这三者的区别,看到两篇置顶文章,估计以后还得回去看看

    http://blog.csdn.net/zwjlpeng/article/details/9746425

    http://www.cnblogs.com/dyllove98/p/3236988.html

  • 相关阅读:
    算法
    什么叫「人的格局」?是否有必要培养大的格局或怎么培养?
    套接字
    信号量 P V测试详解
    Emacs快速入门
    Emacs 从入门到精通
    Linux多进程之间的文件锁
    mysql 登录报错:ERROR 1045 (28000)
    类职责协作模型
    .Netcore使用Session
  • 原文地址:https://www.cnblogs.com/LZYY/p/3442251.html
Copyright © 2011-2022 走看看