• Set集合——HashSet、TreeSet、LinkedHashSet(2015年07月06日)


    一、Set集合不同于List的是:
    Set不允许重复
    Set是无序集合
    Set没有下标索引,所以对Set的遍历要通过迭代器Iterator
    二、HashSet
    1、HashSet由一个哈希表支持,内部实际上是一个HashMap,HashMap的键即为HashSet的值,HashMap的值是一个固定常量,这也就是HashSet中不允许重复的值的原因,因为HashMap的键不允许重复。
    HashSet允许null值,并且只允许一个null值存在,它也是非线程安全的,不过它提供构造线程安全的HashSet的方法
    Set hashSet = Collections.synchronizedSet(new HashSet(...));
    2、HashSet的值不允许重复,那它是怎么保证元素的不重复呢?
    对于加入至HashSet中的元素必须要实现并定义自已的equals()方法,但是对于良好的设计风格,最好在覆盖equals()方法的同时,也覆盖hashCode()方法,在往HashSet中插入新的对象时,首先会用该对象的hashCode()与已经存在对象的hashCode()做比较,如果相等,那就不能插入,如果不等,才会调用equals()方法,如果equals结果为true,说明已经存在,就不能再插入,如果为false,可以插入。
    eg
    User user = new User();
    user.setUserId(1);
    user.setUserName("Dreyer");
    user.setPassword("123456");
    user.setBirthday(new Date());
    User user2 = new User();
    user2.setUserId(1);
    user2.setUserName("Dreyer");
    user2.setPassword("123456");
    user2.setBirthday(new Date());
    HashSet hashSet = new HashSet();
    hashSet.add(user);
    hashSet.add(user2);
    System.out.println("集合大小:"+hashSet.size());
    对以上面的代码,如果User类没有实现equals()、hashCode()方法,则会输出:集合大小:2
    我们给User类增加equals()、hashCode()方法
    @Override
    public boolean equals(Object o) {
    	if (this == o) return true;
    	if (o == null || getClass() != o.getClass()) return false;
    	User user = (User) o;
    	if (userId != user.userId) return false;
    	if (userName != null ? !userName.equals(user.userName) : user.userName != null) return false;
    	return true;
    }
    @Override
    public int hashCode() {
    	int result = userId;
    	result = 31 * result + (userName != null ? userName.hashCode() : 0);
    	return result;
    }
    上面的代码则会输出:集合大小:1
    (实际上是根据hashCode来判断是否相等)
    
    三、TreeSet
    1、TreeSet是基于红-黑树实现的,内部实际上是一个TreeMap,类似于HashSet,TreeSet也不允许重复的元素,也是非线程安全的,同样它也提供构造线程安全的TreeSet方法
    Set TreeSet = Collections.synchronizedSet(new TreeSet(...));不同的是TreeSet不允许null值,如果你试图添加null值,它会抛出NullPointExceptin。
    2、TreeSet的底层实现是采用红-黑树的数据结构,采用这种结构可以从Set中获取有序的序列,但是前提条件是:元素必须实现Comparable接口,该接口中只用一个方法,就是compareTo()方法。当往Set中插入一个新的元素的时候,首先会遍历Set中已经存在的元素,并调用compareTo()方法,根据返回的结果,决定插入位置。进而也就保证了元素的顺序。 如果把没有实现Comparable的对象放入TreeSet中,则会抛出ClassCastException。
    
    四、LinkedHashSet
    1、LinkedHashSet是基于哈希表和链接列表实现的,此实现与 HashSet 的不同之外在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,即按照将元素插入到 set 中的顺序(插入顺序)进行迭代。注意,插入顺序不受在set中重新插入的元素的影响。(如果在 s.contains(e) 返回 true 后立即调用 s.add(e),则元素 e 会被重新插入到 set s 中。)
    2、LinkedHashSet继承自HashSet,所以同样允许null值,不允许重复,LinkedHashSet以元素插入的顺序来维护集合的链接表,允许以插入的顺序在集合中迭代(插入是什么顺序,迭代出来就是什么顺序)
    
    五、使用情况总结
    HashSet是基于哈希表实现的,其性能一般要优于TreeSet,所以在追求效率的时候用HashSet
    TreeSet一般用于有排序需要的情况下
    LinkedHashSet可以用于我们需要维护插入元素的顺序的情况

     

  • 相关阅读:
    归并、希尔排序
    堆排序
    [模板] 最小树形图/朱刘算法
    [模板] 常系数线性递推
    [模板] Kruskal算法 && 克鲁斯卡尔重构树
    [模板] 斯特林数,性质以及求法
    这几天想干什么
    奇怪的 Markdown / LaTeX 笔记
    [模板] 各种莫队
    [模板] 2-SAT 问题
  • 原文地址:https://www.cnblogs.com/Dreyer/p/4625077.html
Copyright © 2020-2023  润新知