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详解的更多相关文章

  1. java中HashSet详解(转)

    HashSet 的实现 对于 HashSet 而言,它是基于 HashMap 实现的,HashSet 底层采用 HashMap 来保存所有元素,因此 HashSet 的实现比较简单,查看 HashSe ...

  2. java中HashSet详解

    HashSet 的实现 对于 HashSet 而言,它是基于 HashMap 实现的,HashSet 底层采用 HashMap 来保存所有元素,因此 HashSet 的实现比较简单,查看 HashSe ...

  3. java集合(4)- java中HashSet详解

    HashSet 的实现 对于 HashSet 而言,它是基于 HashMap 实现的,HashSet 底层采用 HashMap 来保存所有元素,因此 HashSet 的实现比较简单,查看 HashSe ...

  4. Java 容器之Hashset 详解

    Java 容器之Hashset 详解.http://blog.csdn.net/nvd11/article/details/27716511

  5. 最新java数组的详解

    java中HashMap详解 http://alex09.iteye.com/blog/539545 总结: 1.就像引用类型的数组一样,当我们把 Java 对象放入数组之时,并不是真正的把 Java ...

  6. 【转】 java中HashMap详解

    原文网址:http://blog.csdn.net/caihaijiang/article/details/6280251 java中HashMap详解 HashMap 和 HashSet 是 Jav ...

  7. java中HashMap详解(转)

    java中HashMap详解 博客分类: JavaSE Java算法JDK编程生活       HashMap 和 HashSet 是 Java Collection Framework 的两个重要成 ...

  8. java集合(2)- java中HashMap详解

    java中HashMap详解 基于哈希表的 Map 接口的实现.此实现提供所有可选的映射操作,并允许使用 null 值和 null 键.(除了非同步和允许使用 null 之外,HashMap 类与 H ...

  9. java集合框架详解

    java集合框架详解 一.Collection和Collections直接的区别 Collection是在java.util包下面的接口,是集合框架层次的父接口.常用的继承该接口的有list和set. ...

  10. Java集合类的详解与应用

    Java集合类的详解与应用 集合简介: 1.定义:可以同时存储不同类型的数据 他的存储空间会随着数据的增大而增大 2.缺点:只能存储引用数据类型 3.优点:更加合理的利用空间,封装了更多的方法,用起来 ...

随机推荐

  1. 【Linux】5.6 Shell打印输出指令

    Shell打印输出命令 1. echo命令 Shell 的 echo 指令与 PHP 的 echo 指令类似,都是用于字符串的输出.命令格式:echo string 您可以使用echo实现更复杂的输出 ...

  2. DEF4Delphi-master的安装

    保姆教程 d2007的TWEBbrowser因为用的太老的IE内核.现在的浏览器上的功能呈现就卡住了. 那么DEF4Delphi效果非常好. 如何安装后成功运行.很简单.直接去:https://git ...

  3. 自动驾驶 | 为CarLA添加一辆小米SU7 Part I

    自动驾驶 | 为CarLA添加一辆小米SU7 Part I 导言 什么是CarLA? CarLA是一款基于虚幻引擎4(Unreal Engine 4)构建的开源自动驾驶仿真平台,为自动驾驶算法的研发. ...

  4. Transformer(自然语言处理)笔记

    Transerformer架构(自然语言处理) 尝试学习和从零构建一个大语言模型 就目前我的认知 Transformer架构主要分为编码器.解码器.词表.训练集.训练算法(T5) 编码器(Encode ...

  5. Web前端入门第 32 问:CSS background 元素渐变背景用法全解

    渐变背景在 CSS 里面就是一个颜色到另一个颜色渐渐变化的样子. 本文示例中,盒子基础样式: .box { margin: 20px; padding: 20px; border: 10px dash ...

  6. HttpRunner使用总结

    1.安装 打开cmd或cmder,输入命令:pip3 install httprunner 安装完成输入命令:hrun -V或hrun -h 检查安装是否成功 2.使用 1)新建test.yaml文件 ...

  7. Robot Framework全局变量设置

    脚本在每次执行的时候,自定义输入的内容,每次均需要手动去修改 比如,添加商品,上一次执行设置的商品名称为"商品1",这次再执行"商品1"就会导致冲突 如果仅仅是 ...

  8. 遍历表单数据,检查其中任意一项的方法(Get Matching Xpath Count指令的用法)

    如上图,每次新增数据均显示在最上面,且这个表格没有自定义查询的功能. 这给校验添加数据是否成功增加了难度(常规方式是检查第一行数据) 本次案例的逻辑是 使用Get Matching Xpath Cou ...

  9. kettle介绍-Step之CSV Input

    CSV Input/CSV 文件输入介绍 CSV 文件输入步骤主要用于将 CSV 格式的文本文件按照一定的格式输入至 流中 Step name:步骤的名称,在单一转换中,名称必须唯一 Filename ...

  10. Golang解决fatal error: all goroutines are asleep - deadlock!

    今天进行一个协程操作demo时总是报错 //workerpool.go package main import ( "fmt" "time" ) //工作线程 ...