Set集合,放的元素不能重复,请问它的判断重不重复是怎么实现的?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Set集合,放的元素不能重复,请问它的判断重不重复是怎么实现的?相关的知识,希望对你有一定的参考价值。
比如说:ArrayList 和 Vector 是用数组的方式存储的
Set里的 hashSet 和TreeSet是用什么方式存储的?
怎么判断重不重复的?
hashSet 和TreeSet两个的区别是什么?
第一个问题:
TreeSet的底层实现是采用红-黑树的数据结构,采用这种结构可以从Set中获取有序的序列,但是前提条件是:元素必须实现Comparable接口,该接口中只用一个方法,就是compareTo()方法。当往Set中插入一个新的元素的时候,首先会遍历Set中已经存在的元素(当然不是采用顺序遍历,具体采用什么方法,建议自己去看看源码),并调用compareTo()方法,根据返回的结果,决定插入位置。进而也就保证了元素的顺序。
第二个问题:
上面已经说过,加入Set里面的元素必须定义自己的equals()方法,但是对于良好的设计风格,最好在覆盖equals()方法的同时,也覆盖hashCode()方法,当然,对于TreeSet而言不用覆盖hashCode()方法也可。请记住:覆盖hashCode()方法的目的,只有一个原因就是提高效率。
在往Set中插入新的对象时,首先会用该对象的hashCode()与已经存在对象的hashCode()做比较,如果相等,那就不能插入,如果不等,才会调用equals()方法,如果equals结果为true,说明已经存在,就不能再插入,如果为false,可以插入。
注:如果没有覆盖hashCode()方法,那就是只比较equals().对两个对象equals运算,是判断两个对象是否相等的关键。
第三个问题:
2)HashSet与TreeSet区别:
1、TreeSet 是二差树实现的,Treeset中的数据是自动排好序的,不允许放入null值
2、HashSet 是哈希表实现的,HashSet中的数据是无序的,可以放入null,但只能放入一个null,两者中的值都不能重复,就如数据库中唯一约束
3、HashSet要求放入的对象必须实现HashCode()方法,放入的对象,是以hashcode码作为标识的,而具有相同内容的String对象,hashcode是一样,所以放入的内容不能重复。但是同一个类的对象可以放入不同的实例 参考技术A 回答者说的大多是对的 但是对set插入数据的描述是不正确的,对于初级java程序员可能就误导了。
纠正一下:
set中插入数据时,先比较hashCode:
1.如果hashCode相同才会比较equals,equals相同,则两个对象相同,不能插入,equals不同,可以插入;
2.如果hashCode不同,就直接插入了,两个对象hashCode不相等,他们equals一定是false。
Set集合
一、Set集合特点
插入无序,不可指定位置访问。且内部数据不能重复(==或equals)的元素(只要有一个为true就不能重复,重写了equals方法也算)。常用实现类有HashSet、TreeSet。
二、元素不能重复?
1.Set是如何判断元素重复?
HashSet是由HashMap实现的,HashSet.add()引用的是HashMap.put()。
首先通过hashcode判断两对象内存地址哈希值是否相等,如果不相等,则一定不重复。(先通过hashcode快速筛选不相等的对象)。
其次通过equals判断两对象内容是否相等,进而得知两对象最后是否相等。
2. 我们自己写自定义类时一定要重写equals和hashcode方法为判断元素重复提供依据。
三、HashSet
HashSet内部是由HashMap实现的,类内部定义了一个HashMap成员变量。本质就是数组+链表+红黑树。
private transient HashMap<E,Object> map;
既然底层实用hashmap实现的,那么键值对分别对应的是什么呢?让我们走进add方法。
public boolean add(E e) { return map.put(e, PRESENT)==null; }
哦?可以看出我们要添加的元素是作为mao的key的,那作为value的PRESENT是啥呢?
// Dummy value to associate with an Object in the backing Map:与备份映射中的对象关联的虚拟值 private static final Object PRESENT = new Object();
综上可知:HashSet底层使用hashmap实现,键:我们操作的元素,即集合中的数据,值:为同一个Object对象
四、TreeSet
TreeSet是基于TreeMap实现的,本质就是红黑树。插入无序,内部排序,即按照对象特性进行排序。
继承关系:
public class TreeSet<E> extends AbstractSet<E> implements NavigableSet<E>, Cloneable, java.io.Serializable
TreeSet中含有一个"NavigableMap类型的成员变量"m,而m实际上是"TreeMap的实例"。TreeMap也实现NavigableMap接口。
构造方法:
TreeSet(NavigableMap<E,Object> m) { this.m = m; } public TreeSet() { this(new TreeMap<E,Object>()); } public TreeSet(Comparator<? super E> comparator) { this(new TreeMap<>(comparator)); } public TreeSet(Collection<? extends E> c) { this(); addAll(c); } public TreeSet(SortedSet<E> s) { this(s.comparator()); addAll(s); }
HashSet 效率要高于TreeSet,因为HashSet采用散列算法快速对集合进行增删改查 时间复杂度更是几乎接近O(1),但内部无序。
TreeSet 内部有序,可根据指定规则去排序。但效率要比较HashSet低。时间复杂度位O(log n)。
五、LinkedHashSet
LinkedHashSet具有Set不可重复的特点,也有插入排序的特点。其底层是由LinkedHashMap来维护的,其维护着一个运行于所有条目的双重链接列表,此链接列表顶一个迭代顺序(插入顺序或者访问顺序)。
以上是关于Set集合,放的元素不能重复,请问它的判断重不重复是怎么实现的?的主要内容,如果未能解决你的问题,请参考以下文章