1.概述 HashSet的底层实际上就是HashMap,只不过 HashSet是实现了Set接口,并且把数据作为key值,而具体的value值一直使用一个相同的虚值来实现的。由于HashMap的key值不允许重复,并且在HashMap中如果出现key值相同时,会使用新的value覆盖就有value,然后返回就有的value值,那么在hashset中执行这句话就会返回一个false,表示插入失败,这样就能保证了数据的不可重复性。
private transient HashMap<E,Object> map;
private static final Object PRESENT = new Object();
HashSet采用hash算法来存储集合中的元素,因此具有良好的读写性能。 调用add方法向HashSet中添加元素时,首先是针对对象的hashcode值进行比较。如果两个对象的hashcode值相等时才会继续调用equals方法;如果两个对象的hashcode值不相等,则不会调用equals方法。 要求:定义类时如果equals为true,则hashcode值必须相等;但是hashcode值相等不一定equals为true。 2.HashSet特征 无序。不仅不能保证元素的插入顺序,而且在元素以后的顺序也可能会发生变化。 如果需要访问的顺序和插入的顺序一致,则可以使用HashSet的子类LinkeHashSet。 存储的元素不允许重复【equals和hashcode】 3.常用方法 构造器
public HashSet() {
map = new HashMap<>();
}
contains(Object):boolean 判断set中是否存在指定对象,如果存在返回为true。
public boolean contains(Object o) {
return map.containsKey(o);
}
iterator():Iterator 迭代访问元素–foreach写法要求必须实现Iterable接口。
Set<String> set=new HashSet<>();
for(int i=0;i<10;i++) set.add("str-"+i);
Iterator<String> it=set.iterator();
while(it.hasNext()){
String tmp=it.next();
System.out.println(tmp);
}
toArray():Object[] 放回包含所有元素的数组;如果需要指定返回数组的类型,可以使用toArray(类型[]) add(Object obj):boolean 如果set中不存在指定的元素obj,则向set中添加元素。 remove(Object):boolean 删除指定元素 4.LinkedHashSet LinkedHashSet是HashSet的子类,在HashSet的基础上添加了额外的链表,底层采用的是hash表的算法和链表的算法,既能保证元素的添加顺序,也保证了查询效率,当时整体性能要低于HashSet。
Set<String> set = new LinkedHashSet<>();
for (int i = 0; i < 10; i++)
set.add("str_" + i);
set.forEach(System.out::println);
额外添加的链表结构
static class Entry<K,V> extends HashMap.Node<K,V> {
Entry<K,V> before, after;
Entry(int hash, K key, V value, Node<K,V> next) {
super(hash, key, value, next);
}
}
使用链表记录元素的添加位置,使用哈希表保证元素的唯一性。
|