/**
* Set接口继承Collection接口 没有增加方法 set集合无序元素互异(equals()false)
* List接口继承Collection接口 增加了索引相关的方法 使容器有序可重复
* HashSet为Set接口的实现类 使用hash哈希/散列算法实现 允许有null元素 线程不安全
*/
public class TestHashSet {
public static void main(String[] args) {
Set
//HashSet集合可以通过Set引用类型引用
hs1.add("a");
hs1.add("b");
hs1.add("c");
hs1.add("A");
hs1.add("b");
for (String e :
hs1) {
System.out.print(e+",");
}
//Set没有索引index 没有.get(index) 不能通过for(i)遍历
//结果a,A,b,c, Set集合无序 放入的顺序abcA和取出的顺序aAbc不同 Set集合互异 两个"b"只能存在一个
System.out.println();
// hs1.remove();hs1.clear();hs1.contains();hs1.size();hs1.toArray();等方法和List用法相同
/*
保持元素互异的大致原理为每增加一个元素时先.hashCode()计算该元素的hash值 再用hash值计算出元素应当保存在集合中的位置,如果当前位置没有元素则说明集合中没有与之重复的元素 之后完成添加
如果当前位置存在元素则将进一步判断(&&短路与)指针是否相同/指向同一地址或者(||短路或)equals()相等 ture即判断为同一元素 不进行添加
HashSet通过HashMap的哈希表和哈希桶存储元素 哈希表为存放哈希值的数组 每一个元素根据.hashCode()返回的哈希值存放于数组中对应的index
哈希表数组中每一位都是一个哈希桶 哈希桶为单链表 保存表头结点 每一个元素通过index存放入链表中 当元素存放位置重复时新元素会添加到链表的表尾结点
*/
}
}
class Element1{
//自定义类测试HashSet集合的互异
int id;
String info;
public Element1(int id, String info) {
this.id = id;
this.info = info;
}
@Override
public String toString() {
//generate自动生成toString的重写
return "Element1{" +
"id=" + id +
", info='" + info + '\'' +
'}';
}
public static void main(String[] args) {
Set
//创建一个存放自定义类Element1对象的集合
Element1 e1 = new Element1(1,"属性的值完全相同");
Element1 e2 = new Element1(1,"属性的值完全相同");
hs.add(e1);
hs.add(e2);
System.out.println(hs);
//结果为[Element1{id=1, info='属性的值完全相同'}, Element1{id=1, info='属性的值完全相同'}]
//两个内容完全相同的对象 因为.hashCode()值不同被判定为不同的元素
}
}
class Element2{
//更改类的.hashCode()方法 同时还需要更改.equals()方法 实现自定义对象的集合存储互异判定
int id;
String info;
public Element2(int id, String info) {
this.id = id;
this.info = info;
}
//generate 自动生成equals() and hashCode()
@Override
public boolean equals(Object o) {
System.out.println("哈希值相同才会执行equals");
if (this == o) return true;
//先判断指针是否相同
if (o == null || getClass() != o.getClass()) return false;
//判断形参o是否为空 以及this和o是否同类
Element2 element2 = (Element2) o;
//强转o
return id == element2.id && Objects.equals(info, element2.info);
//分别判断每个属性是否相同(&&短路与) info是对象,还需要调用对象.equals()判断
}
@Override
public int hashCode() {
System.out.println("先判断哈希值");
return Objects.hash(id, info);
//将id,info作为key/参数来计算哈希值 代替类对象的哈希值 这样当两个对象的id和info内容相同时计算出的哈希值相同
}
@Override
public String toString() {
return "Element2{" +
"id=" + id +
", info='" + info + '\'' +
'}';
}
public static void main(String[] args) {
Set
Element2 e1 = new Element2(1,"属性的值完全相同");
Element2 e2 = new Element2(1,"属性的值完全相同");
hs.add(e1);
hs.add(e2);
System.out.println(hs);
/*结果为:
先判断哈希值
先判断哈希值
哈希值相同才会执行equals
[Element2{id=1, info='属性的值完全相同'}]
*/
//每次add添加元素会计算哈希值 通过哈希值找index 存e1时index为空,不需要调用equals()直接存入元素 存e2时index存放了e1 哈希值会随元素一起存储,所以不需要第二次计算e1的哈希值
//当index存在元素时才会执行equals 所以两次添加只在存e2时执行了一遍
//通过哈希值和equals判断两个对象相同 只保留了e1 这样实现了通过属性判断互异
}
}
留言与评论(共有 0 条评论) “” |