java SE 集合(四)

来源:互联网 发布:gif编辑文字软件 编辑:程序博客网 时间:2024/05/20 21:22

预备知识:在java中Object类中的hashcode();方法返回该对象的内存真实地址的整数化表示,这个形象的不是真实地址的整数值就是哈希码

Set接口是collection 的另一个子接口本节将分析Set接口,以下内容来自(API)

public interface Set<E>
extends Collection<E>

一个不包含重复元素的 collection。更确切地讲,set 不包含满足 e1.equals(e2) 的元素对 e1e2,并且最多包含一个 null 元素。正如其名称所暗示的,此接口模仿了数学上的set 抽象。

在所有构造方法以及 addequalshashCode 方法的协定上,Set 接口还加入了其他规定,这些规定超出了从Collection 接口所继承的内容。出于方便考虑,它还包括了其他继承方法的声明(这些声明的规范已经专门针对Set 接口进行了修改,但是没有包含任何其他的规定)。 

Set的实现类

HashSet:HashSet 类按照哈希算法来存取集合中的对象,具有很好的存取和查找性能,当向集合中加入一个对象时,HashSet会调用hashcode()方法来获得哈希码,然后根据这个哈希码进一步计算出对象在集合中的存放位置;哈希表里可以存储元素的位置称作“桶”,通常情况下,单个桶里只存放一个元素,此时哈希表有最好的性能,哈希算法可以根据哈希码算出桶的存储位置,接着从桶中取出元素,但是当发生哈希冲突时,一个桶中存放大于一个的元素,这些元素一链表存储,必须按顺序搜索。

 


由一个类创建的对象哈希码是不同的,所以哪怕对象的内容一样,也有不一样的哈希码,就会被放在不同的桶中,那么就违反了Hashset中不允许重复元素的约定,此刻有必要重写她的hashcode()方法,使其哈希码一样那么就会在同一个桶中通过重写equals方法使其返回true那么相同的元素就无法放进HashSet集合


对于 HashSet 而言,它是基于 HashMap 实现的,HashSet 底层采用 HashMap 来保存所有元素,因此 HashSet 的实现比较简单,查看 HashSet 的源代码,可以看到如下代码: 

Java代码  收藏代码
  1. public class HashSet<E>   
  2.  extends AbstractSet<E>   
  3.  implements Set<E>, Cloneable, java.io.Serializable   
  4. {   
  5.  // 使用 HashMap 的 key 保存 HashSet 中所有元素  
  6.  private transient HashMap<E,Object> map;   
  7.  // 定义一个虚拟的 Object 对象作为 HashMap 的 value   
  8.  private static final Object PRESENT = new Object();   
  9.  ...   
  10.  // 初始化 HashSet,底层会初始化一个 HashMap   
  11.  public HashSet()   
  12.  {   
  13.      map = new HashMap<E,Object>();   
  14.  }   
  15.  // 以指定的 initialCapacity、loadFactor 创建 HashSet   
  16.  // 其实就是以相应的参数创建 HashMap   
  17.  public HashSet(int initialCapacity, float loadFactor)   
  18.  {   
  19.      map = new HashMap<E,Object>(initialCapacity, loadFactor);   
  20.  }   
  21.  public HashSet(int initialCapacity)   
  22.  {   
  23.      map = new HashMap<E,Object>(initialCapacity);   
  24.  }   
  25.  HashSet(int initialCapacity, float loadFactor, boolean dummy)   
  26.  {   
  27.      map = new LinkedHashMap<E,Object>(initialCapacity   
  28.          , loadFactor);   
  29.  }   
  30.  // 调用 map 的 keySet 来返回所有的 key   
  31.  public Iterator<E> iterator()   
  32.  {   
  33.      return map.keySet().iterator();   
  34.  }   
  35.  // 调用 HashMap 的 size() 方法返回 Entry 的数量,就得到该 Set 里元素的个数  
  36.  public int size()   
  37.  {   
  38.      return map.size();   
  39.  }   
  40.  // 调用 HashMap 的 isEmpty() 判断该 HashSet 是否为空,  
  41.  // 当 HashMap 为空时,对应的 HashSet 也为空  
  42.  public boolean isEmpty()   
  43.  {   
  44.      return map.isEmpty();   
  45.  }   
  46.  // 调用 HashMap 的 containsKey 判断是否包含指定 key   
  47.  //HashSet 的所有元素就是通过 HashMap 的 key 来保存的  
  48.  public boolean contains(Object o)   
  49.  {   
  50.      return map.containsKey(o);   
  51.  }   
  52.  // 将指定元素放入 HashSet 中,也就是将该元素作为 key 放入 HashMap   
  53.  public boolean add(E e)   
  54.  {   
  55.      return map.put(e, PRESENT) == null;   
  56.  }   
  57.  // 调用 HashMap 的 remove 方法删除指定 Entry,也就删除了 HashSet 中对应的元素  
  58.  public boolean remove(Object o)   
  59.  {   
  60.      return map.remove(o)==PRESENT;   
  61.  }   
  62.  // 调用 Map 的 clear 方法清空所有 Entry,也就清空了 HashSet 中所有元素  
  63.  public void clear()   
  64.  {   
  65.      map.clear();   
  66.  }   
  67.  ...   
  68. }   




0 0