一、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可以用于我们需要维护插入元素的顺序的情况
时间: 2024-10-28 21:26:51