HashSet
要了解HashSet之前最好先了解HashMap,因为看下源代码就可以发现所谓的Set借口下的实现,底层都是基于Map来保存数据的。
JAVA常用数据结构——Map(HashMap、LinkedHashMap、TreeMap)
java实现原理
public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable{
static final long serialVersionUID = -5024744406713321676L;
private transient HashMap<E,Object> map;
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
//......
}
此时可以看到HashSet内部维护了一个HashMap<E,Object> map
,在其构造函数中可以看到
public HashSet() {
map = new HashMap<>();
}
其内部维护了一个HashMap用来进行数据保存数据
基础操作
新增数据
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
可以看到其保存数据的内容非常简单,就是向Map中将元素作为key保存进Map中,值为一个固定的值。
删除
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
删除也是一个非常简单的逻辑,只是简单的移除Map中的值。并没有其他操作。
查询
public Iterator<E> iterator() {
return map.keySet().iterator();
}
其实从插入值得时候就可以看出来,其主要是通过将元素保存到Map中的key中,通过这样保存元素的。所以取出元素的时候只需要获取map的key的集合获得的就是保存的元素的内容。
关于HashSet
对于 HashSet 而言,它是基于 HashMap 实现的,HashSet 底层使用 HashMap 来保存所有元素,因此 HashSet 的实现比较简单。当然实际上你看过后面的几个Set实现后会发现所有的Set都很简单,因为都是基于对应Map的实现来做的。
LinkedHashSet
LinkedHashSet基于LinkedHashMap。之前了解过LinkedHashMap可以知道,和HashMap相比,其内部维护了个LinkedList来维护元素的顺序,所以基于LinkedHashMap的LinkedHashSet同样可以保持元素的插入顺序。
java实现原理
在之前HashSet
中可以发现其内部维护的map并没有直接初始化掉,而是在构造函数中初始化了map的对象。其实这么做的原因是为其他Set实现类提供方法可以实现不同的Map类型。
public LinkedHashSet() {
super(16, .75f, true);
}
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
LinkedHashSet
的构造函数中可以看到,其调用了HashSet的构造函数。而对应的构造函数中,初始化的为LinkedHashMap。
基础操作
LinkedHashSet的代码非常非常简单。除去注释后,其代码甚至不到50行其基础操作就全部重用的HashSet的内容,区别在于,HashSet内部此时初始化的为LinkedHashMap。
package java.util;
public class LinkedHashSet<E>
extends HashSet<E>
implements Set<E>, Cloneable, java.io.Serializable {
private static final long serialVersionUID = -2851667679971038690L;
public LinkedHashSet(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor, true);
}
public LinkedHashSet(int initialCapacity) {
super(initialCapacity, .75f, true);
}
public LinkedHashSet() {
super(16, .75f, true);
}
public LinkedHashSet(Collection<? extends E> c) {
super(Math.max(2*c.size(), 11), .75f, true);
addAll(c);
}
@Override
public Spliterator<E> spliterator() {
return Spliterators.spliterator(this, Spliterator.DISTINCT | Spliterator.ORDERED);
}
}
关于LinkedHashMap如何进行增删查改可以查看之前的文章:
JAVA常用数据结构——Map(HashMap、LinkedHashMap、TreeMap)
TreeSet
TreeSet是JAVA中集合的一种有序集合,它的作用是提供有序的Set集合。
java实现原理
public class TreeSet<E> extends AbstractSet<E>
implements NavigableSet<E>, Cloneable, java.io.Serializable {
/**
* The backing map.
*/
private transient NavigableMap<E,Object> m;
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
public TreeSet() {
this(new TreeMap<E,Object>());
}
TreeSet(NavigableMap<E,Object> m) {
this.m = m;
}
}
可以看奥其内部使用了NavigableMap
来进行数据保存,而这个NavigableMap
可以看到在构造函数中被初始化为TreeMap
public TreeSet() {
this(new TreeMap<E,Object>());
}
基础操作
public boolean add(E e) {
return m.put(e, PRESENT)==null;
}
public boolean remove(Object o) {
return m.remove(o)==PRESENT;
}
可以看到其内部在新增和删除依旧和之前Set实现类一样,就是简单的将被添加元素作为key放入到Map中。
/**
* @throws NoSuchElementException {@inheritDoc}
*/
public E first() {
return m.firstKey();
}
/**
* @throws NoSuchElementException {@inheritDoc}
*/
public E last() {
return m.lastKey();
}
当然可以看到,因为是基于TreeMap的,因为TreeMap提供了一些特有的方法,所以TreeSet中这些新的方法被体现出来了。
关于Set
关于Set的内容,可以发现其基本上是使用了Map的功能实现了自己的逻辑,其中很少或者几乎没有太多自己的业务逻辑。
个人水平有限,上面的内容可能存在没有描述清楚或者错误的地方,假如开发同学发现了,请及时告知,我会第一时间修改相关内容。假如我的这篇内容对你有任何帮助的话,麻烦给我点一个赞。你的点赞就是我前进的动力。
转载:https://blog.csdn.net/qq330983778/article/details/101692002