Set接口的特点:
import javax.swing.text.html.HTMLDocument;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

/*使用hashset存储字符串并遍历
* set集合的特点:
*  1 无序(存储和读取的顺序有可能不一样)
*  2 元素不允许重复,要求元素唯一 最多只有一个null元素
*  3 没有索引*/
public class HashSetDemo {
    public static void main(String[] args) {
        //创建集合对象
        HashSet<String> hs = new HashSet<String>();
        Set<String> set = new HashSet<String>(); //父接口引用指向子类对象
        //添加元素对象
        set.add("hello");
        set.add("world");
        set.add("java");
        //遍历集合对象 转数组 迭代器 增强for
        //转数组
        Object[] obj = set.toArray();
        for (int i = 0; i < obj.length; i++) {
            System.out.println(obj[i]);
        }
        //迭代器
        Iterator<String> it = set.iterator();
        while (it.hasNext()) {
            String s = it.next();
            System.out.println(s);
        }
        //增强for
        for (String s : set) {
            System.out.println(s);
        }
    }
}

HashSet 存储自定义对象并遍历及解决HashSet中的去重问题。

import java.util.HashSet;
import java.util.Objects;

/*
* 利用HashSet存储自定义对象并遍历
* 分析为什么hashset存储自定义对象时没有去重:
* 通过查看源码发现:
* HashSet的add方法,首先会使用当前集合中的每一个元素和新添加的元素将进行hash值比较,如果hash值不一样则直接添加新的元素
* 如果hash值一样,比较地址值或者使用equals方法进行比较
* 如果比较结果一样 则以为是重复不添加
* 所有的比较结果都不一样则添加*
* 改进我们的程序 使HashSet存储自定义对象并去重
* 1 重写hashCode()方法 使其返回一样的哈希值
* 2 重写equals()方法 来比较是否有重复的对象
*
* hashcode()和equals()方法的改进
*/
public class HashSetDemo2 {
    public static void main(String[] args) {
        //创建集合对象
        HashSet<Student> hs = new HashSet<Student>();
        //创建元素对象
        Student s1 = new Student("zhangsan",18);
        Student s2 = new Student("lisi",20);
        Student s3 = new Student("lisi",20);
        //添加元素对象
        hs.add(s1);
        hs.add(s2);
        hs.add(s3);
        //遍历集合对象
        for (Student student:hs) {
            System.out.println(student.age);
        }
    }
}
class Student{
    String name;
    int age;
    public Student(String name,int age)
    {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public boolean equals(Object o) {    //重写equals方法
        System.out.println("sssssssssssssss");
    Student s = (Student)o; //向下转型 可以获取子类特有成员
        if(this.age!=s.age)
            return false;
        if(!this.name.equals(s.name))
            return false;
        return true;
    }

    @Override
    public int hashCode() {    //使hash值一样 这样才能用equals方法进行比较
        return 1;
    }
}

HashSet去重方法的改进:

import java.util.HashSet;
import java.util.Objects;

/*
传统的去重:使HashSet存储自定义对象并去重
* 1 重写hashCode()方法 使其返回一样的哈希值
* 2 重写equals()方法 来比较是否有重复的对象
hashcode()和equals()方法的改进
我们发现放hashcode方法永远返回整数一时,所有对象的哈希值都是一样的
有一些对象的成员变量完全不同,但是他们还需要hash和equals方法的比较
如果我们可以让成员变量不同的对象,他们的哈希值不同,这就可以减少一部分equals方法的比较
可以尝试这让hashcode方法的返回值和对象的成员变量有关 例:hashcode的返回值不是return 1,而是return age;这样就减少了一部分equals方法的比较
可以让hashcode方法返回所有成员变量之和,让基本类型可以直接相加,然后引用数据类型,获取hashcode返回值后再相加(boolean类型不可以参加运算)
return age+name.hashcode(); 效率相对提高了很多
* */
public class HashSetDemo3 {
    public static void main(String[] args) {

        //创建集合对象
        HashSet<Person> hs = new HashSet<Person>();
        //创建元素对象
        Person s1 = new Person("zhangsan",18);
        Person s2 = new Person("lisi",20);
        Person s3 = new Person("lisi",20);
        //添加元素对象
        hs.add(s1);
        hs.add(s2);
        hs.add(s3);
        //遍历集合对象
        for (Person person:hs) {
            System.out.println(person.age);
        }
    }
}
 class Person{
   public String name;
    public int age;
    public Person(String name,int age)
    {
        this.name = name;
        this.age = age;
    }

     @Override
     public String toString() {
         return "Person{" +
                 "name='" + name + '\'' +
                 ", age=" + age +
                 '}';
     }

     @Override
     public boolean equals(Object o) {
         System.out.println("............");
         //提高效率
         if(this == o)                       //向下转型之前的这些都是为了提高程序的健壮性
             return true;
         if(this.getClass()!=o.getClass())
             return false;

        Person p = (Person)o;    //向下转型
         if(this.age!=p.age)
             return false;
         if(!this.name.equals(p.name))
             return false;
         return true;
     }

     @Override
     public int hashCode() {
         return age+name.hashCode();
     }
 }