java集合HashSet类

/**

* Set接口继承Collection接口 没有增加方法 set集合无序元素互异(equals()false)

* List接口继承Collection接口 增加了索引相关的方法 使容器有序可重复

* HashSet为Set接口的实现类 使用hash哈希/散列算法实现 允许有null元素 线程不安全

*/

public class TestHashSet {

public static void main(String[] args) {

Set hs1 = new HashSet<>();

//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 hs = new HashSet<>();

//创建一个存放自定义类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 hs = new HashSet<>();

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 条评论) “”
   
验证码:

相关文章

推荐文章