java Set HashSet详解
Set集合
就像把对象随意扔进罐子里,无法记住元素的添加顺序。Set某种程度就是Collection,方法没有不同,只是行为稍微不同,(不允许重复元素),如果一定要往里加两个相同元素,添加失败add()返回false;
上面的Set的一些共同点,Hashset,TreeSet,EunmSet三个实现类还各有特色。
依次介绍下
Hashset
判断Hashset 集合里的两个对象相等,过两关,equal()比较相等,对象的hashcode()也相等
为什么还得比较对象的hashcode()?
Hashset 集合收进一个对象时,会调用对象的hashcode()得到其Hashcode值来决定他的存储位置。所以,即使是equal()比较相等的两个对象,hashcode不同,存放在hashset里的位置不同,依然能把这两个对象添加成功。
注意:把对象装进hashset时,如果要重写equals方法,也得重写hashcode 方法,因为equals()相等的两对象hashcode 也是相同的。
提问:hashcode()对hashset是很重要的吗?
答:hash算法是快速查找被检索的对象。通过对象的hashcode定位集合里的对象的存储位置。定位该元素。对比下,数组是存储一组元素最快的数组结构,数组通过索引找到它的组员,通过索引能计算元素在内存里的存储位置。
但是为嘛有了数组,还用hashset呢?数组也有局限性,索引是连续的,而且长度不可变。
hashset有了hashcode,所以能快速定位对象位置,而且任意增加对象。
重写hashcode() 注意java.lang.Object中对hashCode的约定:
两个对象通过equals()比较相等时,他们的hashcode 也应该是一样的。
程序运行过程中,同一个对象多次调用hashcode方法返回应该是一样的。
如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么在两个对象中的任一对象上调用 hashCode 方法不一定会生成不同的整数结果。但是,为不相等的对象生成不同整数结果可以提高哈希表的性能。 实际上,由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。
向hashset里添加了一个可变对象后时,要注意:如果后面的程序修改了这个可变对象的实例变量时,可能会导致他与集合里的其他元素相同,即两个对象equals返回true,hashcode也相同。导致hashSet不能正确操作那些元素。
补充了解下,可变对象:创建后,对象的属性值可能会变,也就是说,创建后对象的hash值可能会改变。
举例:对象MutableKey的键在创建时变量 i=10 j=20,哈希值是1291。然后我们改变实例的变量值,该对象的键 i 和 j 从10和20分别改变成30和40。现在Key的哈希值已经变成1931。显然,这个对象的键在创建后发生了改变。所以类MutableKey是可变的。
下面代码是hashset里添加了一个可变对象例子,
可看出,hashset已经添加了几个成员后,修改一个成员的实例变量,会得到里面有相同的成员,因此是不对的。
但是,对最后一行,不能准确访问成员这个。有点疑问,待解决。
package Test01; import java.util.HashSet;
import java.util.Iterator; class mutClass{
public int count;
public mutClass(int count) {
this.count =count;
}
public boolean equals(Object obj) {
if(this == obj) {
return true;
}
if(obj != null && obj.getClass() == mutClass.class) {
mutClass m =(mutClass) obj;
return this.count == m.count;
}
return false;
}
public int hashcode() {
return this.count;
}
public String toString() {
return "试试mutClass[count=" + count + "]";
} }
public class TestHashSet {
@SuppressWarnings("unchecked")
public static void main(String[] args){
HashSet testHashSet =new HashSet(); mutClass a = new mutClass(3);
mutClass b = new mutClass(1);
mutClass c = new mutClass(-9);
mutClass d = new mutClass(9);
testHashSet.add(a);
testHashSet.add(b);
testHashSet.add(c);
testHashSet.add(d);
System.out.println("第一次"+testHashSet);
Iterator iterator =testHashSet.iterator();
mutClass first = (mutClass) iterator.next();
first.count=9;
/* testHashSet.remove(new mutClass(3));
testHashSet.remove(b); //与上一行的区别
*/ System.out.println("第二次"+testHashSet);
System.out.println(new mutClass(-9) == new mutClass(-9));
System.out.println("第四次"+testHashSet.contains(new mutClass(-9)));
}
}
hashset不能保证添加成员的顺序,和自己的顺序是一样的,但是引入了一个LinkedHashSet子类,使得它能和hashset一样,靠hashcode 找到他的存储位置,又能维护添加成员的顺序,内部靠一个链表实现,迭代访问集合时有很好的性能。
java Set HashSet详解的更多相关文章
- java中HashSet详解(转)
HashSet 的实现 对于 HashSet 而言,它是基于 HashMap 实现的,HashSet 底层采用 HashMap 来保存所有元素,因此 HashSet 的实现比较简单,查看 HashSe ...
- java中HashSet详解
HashSet 的实现 对于 HashSet 而言,它是基于 HashMap 实现的,HashSet 底层采用 HashMap 来保存所有元素,因此 HashSet 的实现比较简单,查看 HashSe ...
- java集合(4)- java中HashSet详解
HashSet 的实现 对于 HashSet 而言,它是基于 HashMap 实现的,HashSet 底层采用 HashMap 来保存所有元素,因此 HashSet 的实现比较简单,查看 HashSe ...
- Java 容器之Hashset 详解
Java 容器之Hashset 详解.http://blog.csdn.net/nvd11/article/details/27716511
- 最新java数组的详解
java中HashMap详解 http://alex09.iteye.com/blog/539545 总结: 1.就像引用类型的数组一样,当我们把 Java 对象放入数组之时,并不是真正的把 Java ...
- 【转】 java中HashMap详解
原文网址:http://blog.csdn.net/caihaijiang/article/details/6280251 java中HashMap详解 HashMap 和 HashSet 是 Jav ...
- java中HashMap详解(转)
java中HashMap详解 博客分类: JavaSE Java算法JDK编程生活 HashMap 和 HashSet 是 Java Collection Framework 的两个重要成 ...
- java集合(2)- java中HashMap详解
java中HashMap详解 基于哈希表的 Map 接口的实现.此实现提供所有可选的映射操作,并允许使用 null 值和 null 键.(除了非同步和允许使用 null 之外,HashMap 类与 H ...
- java集合框架详解
java集合框架详解 一.Collection和Collections直接的区别 Collection是在java.util包下面的接口,是集合框架层次的父接口.常用的继承该接口的有list和set. ...
- Java集合类的详解与应用
Java集合类的详解与应用 集合简介: 1.定义:可以同时存储不同类型的数据 他的存储空间会随着数据的增大而增大 2.缺点:只能存储引用数据类型 3.优点:更加合理的利用空间,封装了更多的方法,用起来 ...
随机推荐
- Greenplum优化总结
Greenplum优化总结 GP优化需要了解清理缓存.性能监控.执行计划分析等知识.优化主要包含以下四方面: 表.字段,SQL,GP配置.服务器配置,硬件及节点资源. 一. 清理缓存: #!/usr/ ...
- Eclipse 安装Server-Apache Tomcat 选择(Tomcat 9.0选项)
1.打开组件安装 Eclipse→Help→Install New Software 2.输入当前eclipse对应版本(例如:2022-06),选择提示的官方路径 3.选择最底下的Web, XML, ...
- surging 集成SuperSocket预发布版本2.0
一.概述 周末在家试着扩展SuperSocket,因为之前都是只支持.net framework, 后面出现支持.NET CORE 的SuperSocket 2.0 ,然后集成进来和dotnetty ...
- vue3在构建时,使用魔法糖语法时defineProps和defineEmits的注意事项
在 Vue 3.2+ 版本中,可以使用 <script setup> 替代传统的 script标签来编写组件,它提供了更简洁的语法来编写 Composition API 代码. 在 < ...
- jmeter使用之数据关联
- iOS深色模式媒体查询css
@media (prefers-color-scheme: dark) { body { background-color: #000; color: #fff; } }
- test-同步111
视频如何拍? 旅拍技巧 旅拍微电影必拍内容 只要用这个思路,用手机拍也可以,只是相机效果更好一些. #小雨朵 #摄影教学 #旅行vlog #川西美景 #把生活拍成电影 - 抖音 (douyin.com ...
- Nacos简介—2.Nacos的原理简介
大纲 1.Nacos集群模式的数据写入存储与读取问题 2.基于Distro协议在启动后的运行规则 3.基于Distro协议在处理服务实例注册时的写路由 4.由于写路由造成的数据分片以及随机读问题 5. ...
- 通用型产品发布解决方案(SpringBoot+SpringCloud+Spring CloudAlibaba+Vue+ElementUI+MyBatis-Plus+MySQL+Git+Maven)03
通用型产品发布解决方案(基于分布式微服务技术栈:SpringBoot+SpringCloud+Spring CloudAlibaba+Vue+ElementUI+MyBatis-Plus+MySQL+ ...
- spring boot迁移计划 第Ⅰ章 --chapter 1. rust hyper 结合rust nacos-client开发nacos网关 part ② hyper网关
1. toml依赖 hyper = { version = "1", features = ["full"] } tokio = { version = &qu ...