15--API-Set-->HashSet
Set(接口)
概述
set是一个不包含重复元素的集合, 至多包含一个null
set中不能存放重复元素, 常用来去重
数据无序(因为set集合没有下标)。
Set接口的特点:
不重复, 无序, 无索引
常用方法:
返回类型 | 方法名 | 解释 |
---|---|---|
boolean | add(E e) | 添加元素。 |
boolean | addAll(Collection c): | 把小集合添加到大集合中 。 |
boolean : | contains(Object o) | 如果此 collection 包含指定的元素,则返回 true。 |
boolean | isEmpty() : | 如果此 collection 没有元素,则返回 true。 |
boolean | remove(Object o) : | 从此 collection 中移除指定元素的单个实例。 |
Iterator |
iterator(): | 返回在此 collection 的元素上进行迭代的迭代器。 |
int | size() : | 返回此 collection 中的元素数。 |
Objec[] | toArray(): | 返回对象数组 |
HashSet(实现类)
概述:
HashSet是Set接口的实现类, 可以使用Set接口的所有功能, 拥有Set接口的特点, 数据无序, 不重复, 无索引
特点
HashSet底层是哈希表(也叫散列表). 实际上底层维护了一个HashMap
它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null 元素。
常用构造器
方法 | 说明 |
---|---|
HashSet() | 无参构造 |
常用方法:
返回类型 | 方法名 | 解释 |
---|---|---|
boolean | add(E e) | 添加元素。 |
boolean | addAll(Collection c): | 把小集合添加到大集合中 。 |
boolean : | contains(Object o) | 如果此 collection 包含指定的元素,则返回 true。 |
boolean | isEmpty() : | 如果此 collection 没有元素,则返回 true。 |
boolean | remove(Object o) : | 从此 collection 中移除指定元素的单个实例。 |
Iterator |
iterator(): | 返回在此 collection 的元素上进行迭代的迭代器。 |
int | size() : | 返回此 collection 中的元素数。 |
Objec[] | toArray(): | 返回对象数组 |
自定义对象去重:
注意: 去重自定义对象的时候, equals()和hashCode()必须都重写, 这样的话才可以识别两个对象是否相等, 才能达到去重的目的
- hashCode() 是为了让底层运算哈希值是, 可以根据对象的属性值运算, 如果两个对象的属性值一样, 就可以认为是相等的hash值
- equals() 是为了让底层在判断两个对象是否相等时, 让equals()返回true.
//--源码摘抄:HashMap中634行显示。必须满足以下判断条件,才能给自定义对象去重。
if (p.hash == hash &&((k = p.key) == key ||(key!=null&&key.equals(k))))
测试去重
public class Test5_HashSet2 {
public static void main(String[] args) {
//1、创建HashSet对象
HashSet<Student> set = new HashSet<>();
Student s1 = new Student("jack",18);
Student s2 = new Student("rose",20);
Student s3 = new Student("tony",30);
//2、加入set中
set.add(s1);
set.add(s2);
set.add(s3);
//3、set集合不是可以去重吗?-- 能不能把自定义的对象去重呢?-- 暂时没去重!!
Student s4 = new Student("jack",18);
//4、怀疑add()在添加自定义的对象时,没有根据属性去重!!
//if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k))))
//5、为了使两个对象间的hash值一致,我们需要把只要new一次就计算一个hash值这种默认实现方式改掉。
//这时,需要重写hashCode()让此方法运算出来的hash值可以根据对象的属性值运算。
set.add(s4);
System.out.println(s1.hashCode());
System.out.println(s4.hashCode());
System.out.println(set);
}
}
//创建Student类
class Student{
public Student() {}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
private String name ;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
//右键-source-generator equals() and hashCode()-ok
//5、为了使两个对象间的hash值一致,我们需要把只要new一次就计算一个hash值这种默认实现方式改掉。
//这时,需要重写hashCode()让此方法,运算出来的hash值可以根据对象的属性值运算。
@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;
}
//6、为了让两个对象间,比较属性值,需要提供重写的equals()
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) 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;
}
}