JavaDay09-Set、HashSet、LinkedHashSet、TreeSet

Set

1、无序、不重复、无索引
2、方法基本与Collection一致
3、遍历方法:Iterator、增强for、Lambda表达式

  • Set实现类:
    1、HashSet-无序、不重复、无索引;自定义对象需要重写equals和hashCode方法
    2、LinkedHashSet(HashSet的子类)-有序(双链表机制)、不重复、无索引
    3、TreeSet-可排序、不重复、无索引;自定义对象需要实现Comparable接口 重写compareTo方法

哈希值:

1、如果没有重写hashCode方法,哈希值根据地址计算,不同对象的哈希值是不同的
2、重写了hashCode方法,哈希值根据属性值计算,不同对象具有相同属性值的话的哈希值是相同的
3、少部分情况下,不同属性值或者不同地址值计算出来的哈希值也有可能相同,称为哈希碰撞

HashSet

  • JDK8以前:数组+链表 JDK8以后:数组+链表+红黑树
    底层原理:
    1、创建一个默认长度为16、默认加载因子为0.75的数组,数组名为table,加载因子是用来扩容的
    2、根据元素的哈希值跟数组的长度计算出应该存入的位置
    3、存入元素之前需要判断当前位置是否为null,如果为null则直接存入
    4、如果不为null,则表示有元素,调用equals方法比较属性值
    5、属性值一样:不存 属性值不一样:挂在下面,形成链表
  • JDK8以前,新元素存入数组,老元素挂在新元素下面
  • JDK8以后,新元素直接挂在老元素下面

注意:
1、JDK8以后,当链表长度超过8,并且数组长度大于等于64,链表自动转为红黑树
2、如果集合中存储的是自定义对象,那么必须重写hashCode和equals方法

LinkedHashSet

(既要数据去重又要有序)
是HashSet的子类,有序(双链表机制)、不重复、无索引。

TreeSet

  • 能够实现存入集合的元素自动排序

  • 默认排序规则:
    1、数字类型默认从小到大
    2、字符类型默认按照在ASCII中的顺序
    3、自定义对象实现排序的两种规则

规则一:自定义对象通过实现Comparable接口进行排序

public class TreeSetDemo01 {
    public static void main(String[] args) {
        Teacher tea1 = new Teacher("zhangSan", 35);
        Teacher tea2 = new Teacher("lisi", 25);
        Teacher tea3 = new Teacher("wangwu", 29);
        Teacher tea4 = new Teacher("wangliu", 26);

        TreeSet<Teacher> tree1 = new TreeSet<>();
        tree1.add(tea1);
        tree1.add(tea2);
        tree1.add(tea3);
        tree1.add(tea4);

        System.out.println(tree1);
    }
}
class Teacher implements Comparable<Teacher>{//存在TreeSet中需要实现Comparable接口
    private String name;
    private int age;
    
    public Teacher(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String toString() {
        return "Teacher{name = " + name + ", age = " + age + "}";
    }

    //重写Comparable接口的方法,实现自定义对象的排序
    /*
    this:正在添加的节点
    o:已经存在的节点
    compareTo的返回值:
        1、负数,比当前节点小,存左边
        2、正数,比当前节点大,存右边
        3、0,重复数据,舍弃
     */
    @Override
    public int compareTo(Teacher o) {
        //指定排序的规则
        //希望按照年龄的升序进行排列
        return this.age-o.age;
    }
}

规则二:添加比较器comparator

添加比较器comparator
        TreeSet<String> ts = new TreeSet<>((o1, o2)->{
                int i=o1.length()-o2.length();
                i = i==0?o1.compareTo(o2):i;
                return i;
        });
import java.util.Comparator;
import java.util.TreeSet;
//Comparator
public class TreeSetDemo02 {
    public static void main(String[] args) {
        TreeSet<String> ts = new TreeSet<>(new Comparator<String>() {
            /*
            o1:当前添加的元素
            o2:已经在红黑树中存在的元素
            返回值同compareTo
            需求:先按照长度排序,如果长度相同 再按照首字母排序
             */
            @Override
            public int compare(String o1, String o2) {
                int i=o1.length()-o2.length();
                i = i==0?o1.compareTo(o2):i;
                return i;
            }
        });
/*      //改成lambda表达式:(只有函数式接口才能改成lambda表达式)
        TreeSet<String> ts = new TreeSet<>((o1, o2)->{
            int i=o1.length()-o2.length();
            i = i==0?o1.compareTo(o2):i;
            return i;
        });
*/
        ts.add("acd");
        ts.add("afgsf");
        ts.add("fghd");
        System.out.println(ts);
    }
}

注意:
如果两种规则都存在,以规则二为准。通常,自定义对象使用规则一,如果对象中已经存在默认排序规则但是不满足实际使用需求时,可以使用规则二重新创建排序规则

红黑树添加节点规则:

列表总结:
1、元素可重复-ArrayList
2、增删操作多于查询操作-LinkedList
3、元素不重复-HashSet
4、元素不重复且存取顺序一致-LinkedHashSet(效率低于HashSet)
5、元素排序-TreeSet

TreeSet小练习

import java.util.TreeSet;
public class CollectionDemo {
    /*
    需求:创建5个学生对象
    属性:姓名、年龄、语文成绩、数学成绩、英语成绩
    按照总分从高到低输出到控制台
    如果总分一样,按照语文成绩排
    如果语文一样,按照数学成绩排
    如果数学一样,按照英语成绩排
    如果英语一样,按照年龄排
    如果年龄一样,按照姓名的字母顺序排
    如果都一样,认为是同一个学生,不存
     */
    public static void main(String[] args) {
        Student stu1 = new Student("zhangdan", 23, 99, 99, 100);
        Student stu2 = new Student("hangdandan", 24, 98, 98, 90);
        Student stu3 = new Student("changdanzhi", 22, 99, 95, 92);
        Student stu4 = new Student("zhangdandong", 21, 93, 99, 91);
        Student stu5 = new Student("shangdanfeng", 20, 96, 94, 88);
        TreeSet<Student> ts = new TreeSet<>();
        ts.add(stu1);
        ts.add(stu2);
        ts.add(stu3);
        ts.add(stu4);
        ts.add(stu5);
        for (Student t : ts) {
            System.out.println(t);
        }
    }
}
package treeSet;

import javax.naming.Name;

public class Student implements Comparable<Student>{
    private String Name;
    private int age;
    private int scoreChinese;
    private int scoreMath;
    private int scoreEnglish;
    public Student(String Name, int age, int scoreChinese, int scoreMath, int scoreEnglish) {
        this.Name = Name;
        this.age = age;
        this.scoreChinese = scoreChinese;
        this.scoreMath = scoreMath;
        this.scoreEnglish = scoreEnglish;
    }

    /**
     * 获取
     * @return Name
     */
    public String getName() {
        return Name;
    }

    /**
     * 设置
     * @param Name
     */
    public void setName(String Name) {
        this.Name = Name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    /**
     * 获取
     * @return scoreChinese
     */
    public int getScoreChinese() {
        return scoreChinese;
    }

    /**
     * 设置
     * @param scoreChinese
     */
    public void setScoreChinese(int scoreChinese) {
        this.scoreChinese = scoreChinese;
    }

    /**
     * 获取
     * @return scoreMath
     */
    public int getScoreMath() {
        return scoreMath;
    }

    /**
     * 设置
     * @param scoreMath
     */
    public void setScoreMath(int scoreMath) {
        this.scoreMath = scoreMath;
    }

    /**
     * 获取
     * @return scoreEnglish
     */
    public int getScoreEnglish() {
        return scoreEnglish;
    }

    /**
     * 设置
     * @param scoreEnglish
     */
    public void setScoreEnglish(int scoreEnglish) {
        this.scoreEnglish = scoreEnglish;
    }

    public String toString() {
        return "Student{Name = " + Name + ", age = " + age + ", scoreChinese = " + scoreChinese + ", scoreMath = " + scoreMath + ", scoreEnglish = " + scoreEnglish + "}";
    }
    //通过规则一实现自定义对象在TreeSet中排序
    @Override
    public int compareTo(Student o) {
        int scoreAll=this.getScoreChinese()+this.getScoreMath()+this.getScoreEnglish();
        int scoreO=o.getScoreChinese()+o.getScoreMath()+o.getScoreEnglish();

        /* 方法一:
        if (scoreO-scoreAll!=0){
            return scoreO-scoreAll;
        } else if (this.getScoreChinese()-o.getScoreChinese()!=0) {
            return this.getScoreChinese()-o.getScoreChinese();
        }else if (this.getScoreMath()-o.getScoreMath()!=0) {
            return this.getScoreMath()-o.getScoreMath();
        }else if (this.getScoreEnglish()-o.getScoreEnglish()!=0) {
            return this.getScoreEnglish()-o.getScoreEnglish();
        }else if (this.getAge()-o.getAge()!=0) {
            return this.getAge()-o.getAge();
        }else {
            return this.getName().compareTo(o.getName());
        }*/
        //方法二:
        int i=scoreO-scoreAll;
        i=i==0?this.getScoreChinese()-o.getScoreChinese():i;
        i=i==0?this.getScoreMath()-o.getScoreMath():i;
        i=i==0?this.getScoreEnglish()-o.getScoreEnglish():i;
        i=i==0?this.getAge()-o.getAge():i;
        i=i==0?this.getName().compareTo(o.getName()):i;
        return i;
    }
}

posted @ 2023-04-10 15:47  小园初来乍到  阅读(56)  评论(0)    收藏  举报