zoukankan      html  css  js  c++  java
  • 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可以用于我们需要维护插入元素的顺序的情况

     

  • 相关阅读:
    【LeetCode】048. Rotate Image
    【LeetCode】036. Valid Sudoku
    【LeetCode】060. Permutation Sequence
    【LeetCode】001. Two Sum
    【LeetCode】128. Longest Consecutive Sequence
    【LeetCode】081. Search in Rotated Sorted Array II
    【LeetCode】033. Search in Rotated Sorted Array
    顺时针打印矩阵
    矩形覆盖
    二维数组中的查找
  • 原文地址:https://www.cnblogs.com/Dreyer/p/4625077.html
Copyright © 2011-2022 走看看