理解HashSet及使用
(1) 为啥要用HahSet? (2) hashCode 散列码 //String对象的散列码计算 |
那么下面散列码的结果不同也就好解释了。s和t都还是String对象,散列码由内容获得,结果一样。sb和tb是StringBuffer对象,自身没有hashCode方法,只能继承Object的默认方法,散列码是对象地址,当然不一样了。
String s=new String("OK");//散列码: 3030
String t="Ok"; /散列码: 3030
StringBuffer sb=new StringBuffer(s); //散列码:20526976
StringBuffer tb=new StringBuffer(t); //散列码:20527144
(3) HashSet 散列表的内部结构
4) HashSet 如何add机制
假如我们有一个数据(散列码76268),而此时的HashSet有128个散列单元,那么这个数据将有可能插入到数组的第108个链表中(76268%128=108)。但这只是有可能,如果在第108号链表中发现有一个老数据与新数据equals()=true的话,这个新数据将被视为已经加入,而不再重复丢入链表。
HashSet的散列单元大小如何指定?
Java默认的散列单元大小全部都是2的幂,初始值为16(2的4次幂)。假如16条链表中的75%链接有数据的时候,则认为加载因子达到默认的0.75。HahSet开始重新散列,也就是将原来的散列结构全部抛弃,重新开辟一个散列单元大小为32(2的5次幂)的散列结果,并重新计算各个数据的存储位置。以此类推下去.....
(5) 为什么HashSet查找效率提高了。
知道了HashSet的add机制后,查找的道理一样。直接根据数据的散列码和散列表的数组大小计算除余后,就得到了所在数组的位置,然后再查找链表中是否有这个数据即可。
查找的代价也就是在链表中,但是真正一条链表中的数据很少,有的甚至没有。几乎没有什么迭代的代价可言了。所以散列表的查找效率建立在散列单元所指向的链表中的数据要少 。
(6) hashCode方法必须与equals方法必须兼容
如果我们自己定义了一个类,想对这个类的大量对象组织成散列表结构便于查找。有一点一定要注意:就是hashCode方法必须与equals方法向兼容。
//hashCode与equals方法的兼容
public class Employee{
public int id;
public String name="";
//相同id对象具有相同散列码
public int hashCode(){
return id;
}
//equals必须比较id
public boolean equals(Employee x){
if(this.id==x.id) return true;
else return false;
}
}
为什么要这样,因为HashSet不允许相同元素(equals==ture)同时存在在结构中。假如employeeX(1111,“张三”)和employee(1111,"李四"),而Employee.equals比较的是name。这样的话,employeeX和employeeY的equals不相等。它们会根据相同的散列码1111加入到同一个散列单元所指向的列表中。这种情况多了,链表的数据将很庞大,散列冲突将非常严重,查找效率会大幅度的降低。
(6) 总结一下
1、HashSet不能重复存储equals相同的数据 。原因就是equals相同,数据的散列码也就相同(hashCode必须和equals兼容)。大量相同的数据将存放在同一个散列单元所指向的链表中,造成严重的散列冲突,对查找效率是灾难性的。
2、HashSet的存储是无序的 ,没有前后关系,他并不是线性结构的集合。
3、hashCode必须和equals必须兼容, 这也是为了第1点。
import java.util.HashSet;
import java.util.Iterator; public class IteratorTest {
public static void main(String[] args) {
HashSet set = new HashSet();
set.add("a");
set.add("b");
set.add("c");
set.add("d");
set.add("e");
Iterator iter = set.iterator();
while(iter.hasNext()){
String value = (String)iter.next();
System.out.println(value);
}
}
} 也可使用for循环迭代
Java代码
for(Iterator iter = set.iterator();iter.hasNext();){
String value = (String)iter.next();
System.out.println(value);
} 下例中的TreeSet必须要有一个comparator类,才能往里添加Student对象,否则会抛出ClassCastException
Java代码 import java.util.Comparator;
import java.util.TreeSet; public class TreeSetTest {
public static void main(String[] args) {
TreeSet set = new TreeSet(new StudentComparator());
set.add(new Student(80));
set.add(new Student(90));
set.add(new Student(60));
set.add(new Student(70)); System.out.println(set);
}
} class Student{
int score; public Student(int score) {
this.score = score;
} public String toString() {
return String.valueOf(score);
}
} class StudentComparator implements Comparator{ //按学生成绩升序
public int compare(Object o1, Object o2) {
Student s1 =(Student)o1;
Student s2 =(Student)o2;
return s1.score - s2.score;
} }
理解HashSet及使用的更多相关文章
- HashMap和HashSet的区别
理解HashSet及使用 HashMap和HashSet的区别是Java面试中最常被问到的问题.如果没有涉及到Collection框架以及多线程的面试,可以说是不完整.而Collection框架的问题 ...
- 【转】HashSet的用法
原文网址:http://blog.csdn.net/aidesudi/article/details/4720201 Java代码 public class TestHashSet { public ...
- Set集合之HashSet类
HashSet简介 HashSet是Set接口的典型实现,大多数时候使用Set集合时就是使用这个实现类.HashSet按Hash算法来存储集合中的元素,因此具有良好的存取和查找性能. HashSet特 ...
- 一个有意思的 Java HashSet 问题
昨天,在百度的 java吧 看到有人问关于 HashSet 的问题.下面是他贴出的代码: import java.util.HashSet; public class JavaTest { publi ...
- 集合系列 Set(六):HashSet
HashSet 是 Set 集合的哈希实现,其继承了 AbstractSet 抽象类,并实现了 Set 接口. public class HashSet<E> extends Abstra ...
- 20145305 《Java程序设计》第5周学习总结
教材学习内容总结 1.设计错误对象都继承自java.lang.Throwable类 2.Throwable有两个子类:java.lang.Error与java.lang.Exception 3.Err ...
- java知识点总结
一.java 1.容器 1)List Java中ArrayList和LinkedList区别 2)Set 理解HashSet及使用 HashMap和HashSet的区别 3Map HashMap的容量 ...
- java23种设计模式等等。。
23种设计模式http://www.cnblogs.com/maowang1991/archive/2013/04/15/3023236.html 提升Java代码性能和安全性https://blog ...
- 对hashmap,hashset,hashtable的理解
1.首先先理一下java的集合关系,Collection和Map接口是所有集合接口的根结点,其他集合都直接或者间接的实现了他们中的一个:collection下有:list(元素可重复)和set(不可重 ...
随机推荐
- NYOJ 138 找球号(二) (哈希)
题目链接 描述 在某一国度里流行着一种游戏.游戏规则为:现有一堆球中,每个球上都有一个整数编号i(0<=i<=100000000),编号可重复,还有一个空箱子,现在有两种动作:一种是&qu ...
- Redis数据类型之散列(hash)
1. 什么是散列 散列类似于一个字典,是一个<K, V>对的集合,不过这个key和value都只能是字符串类型的,不能嵌套,可以看做Java中的Map<String, String& ...
- 安装完ODTwithODAC112012,出现ORA-12560:TNS:协议适配器错误
参考:http://blog.csdn.net/tan_yixiu/article/details/6762357 操作系统:windows2008 Enterprise 64位 开发工具:VS201 ...
- 服务器Java环境配置
/* 当要在服务器里搭建Java web项目时, 要先配置好Java需要的环境 */ //jdk [root@localhost ~]# cd /usr/local/src [root@localho ...
- Suse Linux下NTP缓慢调整配置,转载至http://www.gpstime.com.cn/
(1)系统内若有使用crontab 进行与时间调整相关的例行性工作排程,应注释掉(命令人工crontab -e修改,删除定时同步任务ntpdate -s ntpserver). (2)修改ntp配置文 ...
- python_异常处理
常用异常种类 AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x IOError 输入/输出异常:基本上是无法打开文件 ImportError 无法引入模块 ...
- CCTF部分赛题分析
这次算是跟着师傅们全程打完了CCTF的线上赛,一些强队的WriteUp也放了出来.这篇文章主要是想跟着大牛的思路把那些题重新再过一遍. PWN3 这个是格式化字符串漏洞的题.printf的格式化串直接 ...
- Pandas DataFrame构造简析
参考书籍:<利用Python进行数据分析> DataFrame简介: DataFrame是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值.字符串.布尔值等).Dat ...
- break、continue多层循环处理
使用break xxx跳出多层循环的代码如下: for(String s: arr){ labelA: for(String ss: arr) { for(String sss: arr) { Sys ...
- C#窗体内嵌外部程序(cmd.exe)的显示【转载】
[DllImport("User32.dll ", EntryPoint = "SetParent")] private static extern IntPt ...