31.set集合>HashSet--LinkedHashSet--TreeSet

1.Set概述

HashSet

添加元素如果重复会默认覆盖之前的元素:

        HashSet hashSet = new HashSet();
        hashSet.add("qqq");
        hashSet.add("www");
        hashSet.add("eee");
        hashSet.add("www");
        System.out.println(hashSet);//[qqq, eee, www]

 HashSet:对集合迭代顺序不作保证:

        HashSet hashSet = new HashSet();
        hashSet.add("qqq");
        hashSet.add("www");
        hashSet.add("eee");
        System.out.println(hashSet);//[qqq, eee, www]

HashSet保证元素唯一性的源码分析:

 注意,是被储存对象对应的类要重写上面的方法:

idea快捷键Alt+Enter:

    @Override
    public boolean equals(Object o) {
        System.out.println("equals被调用");
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Student student = (Student) o;

        if (age != student.age) return false;
        return name != null ? name.equals(student.name) : student.name == null;

    }

    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        return result;
    }

 

 LinkedHashSet

TreeSet

 排序就是默认从小到大的排序

自然排序Comparable:

案例:

 创建学生类Student实现Comparable并重写CompareTo()方法:

public class Student implements Comparable<Student> {

    private String name;
    private int age;
...
...
 @Override
    public int compareTo(Student o) {
        return 0;
    }
}

如果Student没有实现Comparable并重写CompareTo()方法那么下面程序执行就会报错:

 

 如果实现了Comparable并重写CompareTo()方法那么上面程序执行就会打印出如下结果:

 从上面结果我们可以看出,只成功添加了一个元素;这是因为CompareTo()方法一直返回的是0:   "0代表后面添加的元素和第一个元素比较的时候,前后元素完全一样,所以set就不会添加后面的元素了";因此我们需要重写一下CompareTo()方法:

    @Override
    public int compareTo(Student s) {//重写排序规则
//        return 0;//只添加第一个对象,后面对象被视为和第一个对象完全一样而不被添加
//        return 1;//(正数)认为前一个对象比后一个对象大
//        return -1;//(负数)认为前一个对象比后一个对象小
        return this.age-s.age;//结果>0说明上一个学生的年龄大于下一个,就会把大的元素放在后面,然后再和下一个添加元素比较,这样就实现了年龄从小到大的排序
    }

 但是上面我们仅仅是参照年龄来存储并排序的,年龄相同的人只能存进去一个,是很不合理的,所以我们还要根据姓名字段比较,所以上面代码应该优化为:

    public int compareTo(Student s) {//重写排序规则
//        return 0;//只添加第一个对象,后面对象被视为和第一个对象完全一样而不被添加
//        return 1;//(正数)认为前一个对象比后一个对象大
//        return -1;//(负数)认为前一个对象比后一个对象小
        int num=this.age-s.age;//结果>0说明上一个学生的年龄大于下一个,就会把大的元素放在后面,然后再和下一个添加元素比较,这样就实现了年龄从小到大的排序
        int result=num==0?this.name.compareTo(s.name):num;//年龄不同则返回年龄比较结果,否则返回姓名自然排序结果
        return num;
    }

 比较器Comparator:

被操作类Student不需要实现Comparable接口了

    public static void main(String[] args) {
        TreeSet<Student> students = new TreeSet<Student>(new Comparator<Student>() {//使用内部类创建Comparator对象并重写compare方法
            @Override
            public int compare(Student s1, Student s2) {
                int num=s1.getAge()-s2.getAge();
                int result=num==0?s1.getName().compareTo(s2.getName()):num;
                return result;
            }
        });
        Student student1 = new Student("刘备", 28);
        Student student2 =new Student("关于",25);
        Student student3 =new Student("张飞",29);
        Student student4 =new Student("马超",27);
        students.add(student1);
        students.add(student2);
        students.add(student3);
        students.add(student4);
        Iterator<Student> iterator = students.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }
原文地址:https://www.cnblogs.com/luzhanshi/p/13130195.html