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;
    }						
}
                
            
        
浙公网安备 33010602011771号