Set不允许包含相同的元素,如果试图把两个相同元素加入同一个集合中,add方法返回false。
以下是HashMap中添加元素时的检测,判断对象是否是同一个
判断hash是否相等,并且 == 或者 equals为true.
如果添加的对象没用重写equals,其仍然是采用==进行判断.
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
public boolean equals(Object obj) {
return (this == obj);
}
HashMap的key是不允许重复的,HashSet就是依赖这个特性实现其元素值不重复的功能,HashSet是基于HashMap来实现的,其对数据的操作调用的是HashMap的相关方法.具体HashMap的实现原理可以查看Java9.0 HashMap源码阅读记录.
public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable
HashSet只有两个私有属性,一个是HashMap类型,因为HashSet是基于HashMap来实现的.
一个是final Object类型,在执行添加操作时,value都是这个对象,而key是用户要添加的数据.
private transient HashMap map;
private static final Object PRESENT = new Object();
使用默认参数构造一个HashMap对象
public HashSet() {
map = new HashMap<>();
}
指定初始容量,这里这么写的原因我觉得是避免在添加集合元素时出现扩容,而HashMap默认的加载因子是0.75,(c.size()/.75f) + 1确保了添加最后一个元素时不会进行扩容.
public HashSet(Collection extends E> c) {
map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
addAll(c);
}
指定初始容量和加载因子
public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap<>(initialCapacity, loadFactor);
}
指定加载因子
public HashSet(int initialCapacity) {
map = new HashMap<>(initialCapacity);
}
指定初始容量和加载因子,可以忽略.
这里创建的是LinkedHashMap.这个
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
可以看到其调用的是HashMap的put(方法,key为用户要添加的数据,value都是同一个对象.
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
public int size() {
return map.size();
}
public boolean isEmpty() {
return map.isEmpty();
}
public boolean contains(Object o) {
return map.containsKey(o);
}
public void clear() {
map.clear();
}
因为我们是将数据以key方式进行添加,因此迭代器获得的也是key的迭代器.
public Iterator iterator() {
return map.keySet().iterator();
}
创建一个类
class Student{
private String name;
public Student(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
测试
HashSet hashSet = new HashSet();
//对象1
Student student1 = new Student("LiNing");
hashSet.add(student1);
//对象2
Student student2 = new Student("zhanggang");
hashSet.add(student2);
System.out.println("foreach 访问方式");
for(Student stu:hashSet) {
System.out.println(stu.getName());
}
System.out.println("迭代器 访问方式");
Iterator iterator = hashSet.iterator();
while (iterator.hasNext()) {
System.out.println(((Student)iterator.next()).getName());
}
输出
foreach 访问方式
LiNing
zhanggang
迭代器 访问方式
LiNing
zhanggang
JDK9.0 ArrayList源码阅读记录
JDK9.0 LinkedList源码阅读记录
ArrayList和LinkedList性能比较
JDK9.0 Vector源码阅读记录
JDK9.0 Hashtable源码阅读记录
Java9.0 HashMap源码阅读记录
JDK9.0 HashSet源码阅读记录