当前位置: 代码网 > it编程>编程语言>Java > Java HashSet源码剖析

Java HashSet源码剖析

2024年08月06日 Java 我要评论
与HashMap类似,字面上看,HashSet由两个单词组成:Hash和Set。其中,Set表示接口,实现Set接口也有多种方式,各有特点,HashSet实现的方式利用了Hash。下面,我们先看Set接口,然后看实现原理,最后总结分析HashSet的特点。

与hashmap类似,字面上看,hashset由两个单词组成:hash和set。其中,set表示接口,实现set接口也有多种方式,各有特点,hashset实现的方式利用了hash。下面,我们先看set接口,然后看实现原理,最后总结分析hashset的特点。

目录

set

实现原理

特点和应用


set

set表示的是没有重复元素、且不保证顺序的容器接口,它扩展了collection,但没有定义任何新的方法,不过,对于其中的一些方法,它有自己的规范。set接口的定义如下:

public interface set<e> extends collection<e> {
    int size();
    boolean isempty();
    boolean contains(object o);
    // ... (其他方法)

    iterator<e> iterator();
    object[] toarray();
    <t> t[] toarray(t[] a);
    
    boolean add(e e);
    boolean remove(object o);
    boolean containsall(collection<?> c);
    boolean addall(collection<? extends e> c);
    boolean retainall(collection<?> c);
    boolean removeall(collection<?> c);
    void clear();
    boolean equals(object o);
    int hashcode();
}

与hashmap类似,hashset的构造方法有:

   public hashset()
   public hashset(int initialcapacity)
   public hashset(int initialcapacity, float loadfactor)
   public hashset(collection<? extends e> c)

其中initialcapacity和loadfactor的含义与hashmap中的是一样的。与hashmap类似,hashset要求元素重写hashcode和equals方法,且对于两个对象,如果equals相同,则hashcode也必须相同,如果元素是自定义的类,需要注意这一点。

实现原理

hashset内部是用hashmap实现的,它内部有一个hashmap实例变量,如下所示:

private transient hashmap<e,object> map;

我们知道,map有键和值,hashset相当于只有键,值都是相同的固定值,这个值的定义为:

private static final object present = new object();

理解了这个内部组成,它的实现方法也就比较容易理解了,我们来看下hashset的构造方法,主要就是调用了对应的hashmap的构造方法:

 public hashset(int initialcapacity, float loadfactor) {
       map = new hashmap<>(initialcapacity, loadfactor);
}

接受collection参数的构造方法稍微不一样,代码为:

public hashset(collection<? extends e> c) {
       map = new hashmap<>(math.max((int) (c.size()/.75f) + 1, 16));
       addall(c);
}

c.size()1.75f用于计算initialcapacity,0.75f是loadfactor的默认值。

add方法的代码:

public boolean add(e e) {
       return map.put(e, present)==null;
}

调用了map的put方法,元素e用于键,值就是固定值present,put返回null表示原来没有对应的键,添加成功了。hashmap中一个键只会保存一份,所以重复添加hashmap不会变化。

检查是否包含元素,就是检查map中是否包含对应的键。代码为:

public boolean contains(object o) {
       return map.containskey(o);
}

删除元素就是调用map的remove方法,返回值为present表示原来有对应的键且删除成功了。代码为:

public boolean remove(object o) {
       return map.remove(o)==present;
}

迭代器就是返回map的keyset的迭代器,代码为:

public iterator<e> iterator() {
       return map.keyset().iterator();
}

特点和应用

hashset有如下特点:

1)没有重复元素;

2)可以高效地添加、删除元素、判断元素是否存在,效率都为o(1);

3)没有顺序。

hashset有很多应用场景,比如:

1)去重,如果对去重后的元素没有顺序要求,则hashset可以方便地用于去重;

2)保存特殊值,set可以用于保存各种特殊值,程序处理用户请求或数据记录时,根据是否为特殊值判断是否进行特殊处理,比如保存ip地址的黑名单或白名单;

3)集合运算,使用set可以方便地进行数学集合中的运算,如交集、并集等运算,这些运算有一些很现实的意义。比如,用户标签计算,每个用户都有一些标签,两个用户的标签交集就表示他们的共同特征,交集大小除以并集大小可以表示他们的相似程度。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com