2021-04-22Set集合

Set集合概述和特点
Set集合特点
  • 不包含重复元素的集合
  • 没有带索引的方法,所以不能使用普通for循环遍历
    Set 集合练习
  • 存储字符串并遍历
/**
 * HashSet:对集合的迭代顺序不作任何保证
 */
import java.util.HashSet;
import java.util.Set;
public class SetDemo {
    public static void main(String[] args) {
        // 创建集合对象 Set是接口,不能直接实例化
        Set set = new HashSet();
        // 添加元素
        set.add("hello");
        set.add("world");
        set.add("java");
        set.add("hello");
        //遍历
        for (String s : set) {
            System.out.println(s);
        }
    }
}
代码运行截图.png
哈希值

哈希值:是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值

Object类中有一个方法可以获取对象的哈希值

  • public int hashCode(): 返回对象的哈希码值

对象的哈希值特点:

  • 同一个对象多次调用hashCode() 方法返回的哈希值是相同的
  • 默认情况下,不同对象的哈希值是不同的。而重写hashCode()方法,可以实现让不同对象的哈希值相同
HashSet集合概述和特点

HashSet集合特点

  • 底层数据结构是哈希表
  • 对集合的迭代顺序不作任何保证,也就是说不保证存储和取出的元素顺序一致
  • 没有带索引的方法,所以不能使用普通for循环遍历
  • 由于是Set集合,所以是不包含重复元素的集合
HashSet集合保证元素唯一性源码分析

HashSet集合添加到一个元素的过程:


添加元素过程图.png

HashSet集合存储元素:

  • 要保证元素唯一性,需要重写hashCode()equals()
常见数据结构之哈希表

哈希表

  • JDK8之前,底层采用数组+链表实现,可以说是一个元素为链表的数组
  • JDK8之后,在长度比较长的时候,底层实现了优化
HashSet集合存储学生对象并遍历

需求:创建一个存储学生对象的集合,存储多个学生对象,使用程序实现在控制台遍历该集合
要求:学生对象的成员变量值相同,我们认为是同一个对象
思路:

  1. 定义学生类
  2. 创建HashSet对象
  3. 创建学生对象
  4. 把学生添加到集合
  5. 循环遍历(增强for循环)
  6. 在学生类中重写两个方法(此步最为关键,如果缺少此步操作,将会录入成员变量值相同的成员对象。重写方法按下Alt+Insert快捷键即可,找到hashCode()和equals()如下自动生成即可)
    截图.png
LinkedHashSet集合概述和特点
LinkedHashSet集合特点
  • 哈希表和链表实现的Set接口,具有可预测的迭代次序
  • 由链表保证元素有序,也就是说元素的存储和取出顺序是一致的(非元素大小顺序)
  • 由哈希表表示元素唯一,也就是说没有重复的元素
    LinkedHashSet集合练习
public class LinkedHashSetDemo {
    public static void main(String[] args) {
        // 创建对象
        LinkedHashSet lhs = new LinkedHashSet();
        // 添加对象
        lhs.add("hello");
        lhs.add("world");
        lhs.add("java");
        lhs.add("java");
        for (String s : lhs) {
            System.out.println(s);
        }
        System.out.println(lhs);
    }
}
代码运行截图.png
TreeSet集合概述和特点

TreeSet集合特点

  • 元素有序,这里的顺序不是指存储和取出的顺序,而是按照一定的规则进行排序,具体的排序方式取决于构造方法
    TreeSet():根据其元素的自然排序进行排序
    TreeSet(Comparator comparator):根据指定的比较器进行排序
  • 没有带索引的方法,所以不能使用普通for循环遍历[可以使用迭代器和增强for进行循环遍历]
  • 由于是Set集合,所以不包含重复元素的集合
    TreeSet集合练习
public class TreeDemo {
    public static void main(String[] args) {
        TreeSet ts = new TreeSet();  // 基本类型进行存储的时候,
        // 里面用的是对应的包装类类型
        ts.add(7);
        ts.add(39);
        ts.add(28);
        ts.add(20);
        ts.add(40);
        ts.add(20);  // 不包含重复元素

        for (Integer i : ts) {
            System.out.println(i);
        }
    }
}
代码运行结果.png
自然排序Comparable的使用
  • 存储学生对象并遍历,创建TreeSet集合使用无参构造方法
  • 要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
    为满足条件:要让学生类实现Comparable接口
    而且需要进行重写操作
   @Override
    public int compareTo(Student s) {
//        return 0;  // 不存储的元素
//        return 1;   // 升序。按添加顺序存储
//        return -1;   // 降序
//        int num = this.age - s.age;  // 按年龄大小升序:this是s2,s是s1.
        int num = s.age - this.age;   // 按年龄大小升序降序
        int num2 = num == 0?this.name.compareTo(s.name):num;
        return num2;           // 使满足年龄相同姓名不同的学生也可以添加成功
    }
public class TreeSetDemo02 {
    public static void main(String[] args) {
        // 创建集合对象
        TreeSet ts = new TreeSet();
        Student s1 = new Student("xishi",29);
        Student s2 = new Student("wangzhojun",33);
        Student s3 = new Student("diaochao",30);
        Student s4 = new Student("yangyuhuan",28);
        Student s5 = new Student("linqingxie",28);
        Student s6 = new Student("linqingxie",28);
        // 把学生添加到集合
        ts.add(s1);
        ts.add(s2);
        ts.add(s3);
        ts.add(s4);
        ts.add(s5);
        ts.add(s6);
        // 遍历集合
        for(Student s:ts) {
            System.out.println(s.getName()+","+s.getAge());
        }
    }
}
代码运行截图.png

结论

  • 用TreeSet集合存储自定义对象,无参构造方法使用的是自然排序对元素进行排序的
  • 自然排序,就是让元素所属的类实现Comparable接口,重写compareTo(To)方法
  • 重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
比较器排序Comparator的使用
  • 存储学生对象并遍历。创建 TreeSet集合使用带参构造
  • 要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
    结论:
  • 用TreeSet集合存储自定义对象,带参构造方法接收的是比较器排序对元素进行排序的
  • 比较器排序,就是让集合构造方法接收Comparator的实现类对象,重写compare(To1,To2)方法
  • 重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
public class TreeSetDemo02 {
    public static void main(String[] args) {
        // 创建集合对象
        TreeSet ts = new TreeSet(new Comparator() {
            @Override
            public int compare(Student s1, Student s2) {
                // this.age -  s.age
                // s1,s2分别指的时this,s
                int num = s1.getAge() - s2.getAge();
                int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
                return num2;
            }
        });
        Student s1 = new Student("xishi", 29);
        Student s2 = new Student("yangyuhuan", 28);
        Student s3 = new Student("linqingxie", 27);
        Student s4 = new Student("linqingxie", 28);
        // 把学生添加到集合
        ts.add(s1);
        ts.add(s2);
        ts.add(s3);
        ts.add(s4);
        // 遍历集合
        for (Student s : ts) {
            System.out.println(s.getName() + "," + s.getAge());
        }
    }
}

案例:

public class TreeSetDemo01 {
    public static void main(String[] args) {
        TreeSet ts = new TreeSet(new Comparator() {
            @Override
            public int compare(Student s1, Student s2) {
                int i = s1.getSum() - s2.getSum();
                int i2 = i == 0 ? s1.getChinese() - s2.getChinese() : i;
                int i3 = i2 == 0 ? s1.getName().compareTo(s2.getName()) : i2;
                return i3;
            }
        });
        Student s1 = new Student("风清扬", 99, 87);
        Student s2 = new Student("令狐冲", 94, 95);
        Student s3 = new Student("张曼玉", 92, 91);
        Student s4 = new Student("刘岩", 90, 93);
        Student s5 = new Student("刘一备", 90, 93);

        ts.add(s1);
        ts.add(s2);
        ts.add(s3);
        ts.add(s4);
        ts.add(s5);

        for (Student s : ts) {
            System.out.println(s.getName() + "," + s.getChinese() + "," + s.getMath() + " " + s.getSum());
        }
    }
}
代码运行截图.png

案例2:不重复的随机数
需求:编写一个程序,获取10个1-20之间的随机数,要求随机数不能重复,并在控制台输出
思路:

  1. 创建Set集合对象
  2. 创建随机数对象
  3. 判断集合的长度是不是小于10
    是:产生一个随机数,添加到集合
    4.遍历集合
public class SetDemo {
    public static void main(String[] args) {
        // 创建集合对象 Set是接口,不能直接实例化
//        Set set = new HashSet(); //  无序排列
        TreeSet set = new TreeSet();   // 元素大小有序排列输出
//        LinkedHashSet set = new LinkedHashSet(); // 元素存储和取出有序
        // 创建随机数对象
        Random r = new Random();
        // 判断集合的长度是不是小于10
        while (set.size() < 10) {  // 从0 开始比较的
            // 产生一个随机数,添加到集合
            int number = r.nextInt(20) + 1;
            set.add(number);
        }
        // 遍历集合
        for (Integer i : set) {
            System.out.println(i);
        }
    }
}
代码运行截图.png

你可能感兴趣的:(2021-04-22Set集合)