集合:Set实现类HashSet

时间:2022-01-03 18:59:42

java.util.HashSet
1.概述
在学List接口的时候,主要学了它的三个实现类,其中ArrayList、Vector的数据结构是数组;LinkedList的数据结构是链接列表(链表)。数组的特点是:增删慢,查询快;链表的特点是:增删快,查询慢
HashSet的数据结构是哈希表,它是元素为链表的数组,为的是最大程度地综合数组和链表的优点。有点像”分页记笔记”,页码对应哈希值,也可以认为是这个链表数组的索引值;页面内容对应元素链表,存某一类内容。哈希表的查找:先遍历哈希值,再查询元素链表(哈希值越多,元素链表越短,查询越快)。哈希表的增删:先遍历哈希值,再在元素链表中做增删。
2.HashSet如何保证所存元素的不重复
用HashSet存储并遍历字符串
用HashSet存储并遍历自定义对象:出问题:元素重复了
自动解决方案:Alt+Shift+S—Generate hashCode() and equals()…
或自定义类里右击—Source—Generate hashCode() and equals()…
3.延伸知识
常用的ArrayList和LinkedList,有序但元素重复
这里学的HashSet,无序但元素唯一
综合二者:有序且唯一,怎么实现呢?
HashSet的子类:LinkedHashSet就做到这一点了,不演示了

package knowledge_basic_02;
import java.util.HashSet;
class Per
{
public String name;
public int age;
Per(String name,int age){
this.name=name;
this.age=age;
}
//HashSet里的add方法和它里面的hashCode()和equals()有关
//为了保证add元素不重复,必须重写hashCode()和equals()
//此处采用自动重写方案
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Per other = (Per) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}

}
public class HashSetDemo {
public static void main(String[] args) {
//HashSet存储并遍历字符串
HashSet<String> h1=new HashSet<String>();
h1.add("ab");
h1.add("ba");
h1.add("cd");
h1.add("ef");
h1.add("ab");
h1.add("ab");
h1.add("ef");
//增强for遍历
for(String s:h1)
{
System.out.println(s);
}
//HashSet存储并遍历自定义对象
HashSet<Per> h2=new HashSet<Per>();
h2.add(new Per("张三",18));
h2.add(new Per("李四",17));
h2.add(new Per("张三",18));
h2.add(new Per("张三",18));
h2.add(new Per("王五",19));
for(Per p:h2)
{
System.out.println(p.name+" "+p.age);
}
}
}

ab
cd
ef
ba
李四 17
张三 18
王五 19