zoukankan      html  css  js  c++  java
  • 集合(Set)【3】

    集合

    1.Set 集合

    1.1Set 集合概述和特点

    set集合特点

    • 不包含重复元素的集合

    • 没有带索引的方法,所以不能使用普通for循环遍历

    Set集合练习

    • 存储字符串并遍历

    public class SetDemo {
        public static void main(String[] args) {
            //创建Set对象
            Set<String> set = new HashSet<>();
            //添加元素
            set.add("浪浪");
            set.add("学习");
            set.add("java");
    ​
            //遍历Set
            for(String s : set){
                System.out.println(s);
            }
        }
    }

    1.2 哈希值

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

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

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

    对象的哈希值特点

    • 同一个对象多次调用hashCode()方法返回的哈希值是相同的

    • 默认情况下,不同对象的哈希值是不同的。而重写hashCode()方法,可以实现让不同对象的哈希值相同

    学生实体类

    public class Student {
        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;
        }
    ​
        public Student() {
        }
    ​
        public Student(String name, int age) {
            this.name = name;
            this.age = age;
        }
    }

    测试类

    public class SetDemo {
        public static void main(String[] args) {
            Student s1 = new Student("浪浪",20);
            Student s2 = new Student("王五",20);
            Student s3 = new Student("浪浪",20);
    ​
            System.out.println(s1.hashCode());//1163157884
            System.out.println(s2.hashCode());//1956725890
            //默认情况下,不同对象的哈希值是不相同的
            //通过方法重写,可以实现不同对象的哈希值是相同的
            System.out.println(s3.hashCode());//356573597
            System.out.println("*****************");
    ​
            System.out.println("浪浪".hashCode());//896320
            System.out.println("学习".hashCode());//745402
            System.out.println("java".hashCode());//3254818
    ​
            System.out.println("浪浪".hashCode());//896320
            System.out.println("*******************");
    ​
    ​
            System.out.println("重地".hashCode());//1179395
            System.out.println("通话".hashCode());//1179395
        }
    }

    1.3 HashSet集合概述和特点

    hashSet集合特点

    • 底层数据结构是哈希表

    • 对集合的迭代顺序不作任何保证,也就是说不保证存储和取出的元素顺序一致

    • 没有带索引的方法,所以不能使用普通for循环遍历

    • 由于是Set集合,所以是不包含重复元素的集合

    HashSet集合练习

    • 存储字符串并遍历

    1.4 HashSet集合保证元素唯一性源码分析

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

    HashSet集合存储元素:

    • 要保证元素的唯一性,需要重写hashCode 和 equals()

    1.4 常见数据结构之哈希表

    哈希表

    • JDK8之前,底层采用数组+链表实现,可以说是一个元素为链表的数组

    • JDK8以后,在长度比较长的时候,底层实现了优化

    1.5 常见数据结构之哈希表

    案例:HashSet集合存储学生对象并遍历

    需求:创建一个存储学生对象的集合,存储多个学生对象,使用程序实现在控制台遍历该集合

    要求:学生对象的成员变量值相同,我们就认为是同一个对象

    思路:

    ① 定义学生类

    ② 创建HashSet集合对象

    ③ 创建学生对象

    ④ 把学生添加到集合

    ⑤ 遍历集合(增强for)

    ⑥ 在学生实体类中重写hashCode()和equals()方法

    学生实体类

    public class Student {
        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;
        }
    ​
        public Student() {
        }
    ​
        public Student(String name, int age) {
            this.name = name;
            this.age = age;
        }
    ​
        @Override
        public boolean equals(Object o) {
            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;
        }
    }

     

    测试类

    public class HashSetDemo {
        public static void main(String[] args) {
            //创建HashSet集合对象
            HashSet<Student> hs = new HashSet<>();
    ​
            //创建学生对象
            Student s1 = new Student("张三",20);
            Student s2 = new Student("李四",22);
            Student s3 = new Student("王五",21);
            
            Student s4 = new Student("王五",21);
    ​
            //添加到集合中
            hs.add(s1);
            hs.add(s2);
            hs.add(s3);
            hs.add(s4);
    ​
            //遍历增强for
            for (Student s : hs){
                System.out.println(s.getName()+","+s.getAge());
            }
        }
    }

    1.6 LinkedHashSet 集合概述和特点

    LinkedHashSet集合特点

    • 哈希表和链表实现的Set接口,就有可预测的迭代次序

    • 由链表保证元素有序,就就是说元素的存储和取出顺序是一致的

    • 由哈希表保证元素唯一,也就是说没有重复的元素

    LinkedHashSet集合练习

    • 存储字符串并遍历

    测试类

    public class LinkedHashSetDemo {
        public static void main(String[] args) {
            //创建集合对象
            LinkedHashSet<String> linkedHashSet = new LinkedHashSet<>();
    ​
            //添加元素
            linkedHashSet.add("浪浪");
            linkedHashSet.add("学习");
            linkedHashSet.add("java");
    ​
            //由哈希表决定了元素的唯一性
            linkedHashSet.add("java");
            //由链表决定了元素是有序性 元素的存入和读取的顺序是一致的
            for (String s : linkedHashSet
                 ) {
                System.out.println(s);
            }
        }
    }

    1.7 TreeSet集合概述和特点

    TreeSet集合特点

    • 元素有序,这里的顺序不是指存储和读取的顺序,而是按照一定的规则进行排序,具体排列方式取决于构造器

      • TreeSet():根据其元素的自然排列顺序进行排列

      • TreeSet(Comparator comparator):根据指定的比较器进行排序

    • 没有带索引的方法,所以不能使用普通的for循环遍历

    • 由于是Set集合,所以不包含重复元素的集合

    TreeSet集合练习

    • 存储整数并遍历

    public class TreeSetDemo {
        public static void main(String[] args) {
            //创建集合对象
            TreeSet<Integer> ts = new TreeSet<>();
    ​
            //添加元素
            ts.add(10);
            ts.add(40);
            ts.add(35);
            ts.add(15);
            ts.add(66);
    ​
            ts.add(66);
    ​
            //遍历集合
            for (Integer i : ts){
                System.out.println(i);
            }
        }
    }

    1.8 自然排序Comparable的使用

    • 存储学生对象并遍历,创建TreeSet集合使用无参构造方法

    • 要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序

    结论

    • 用TreeSet集合存储自定义对象,无参构造方法使用的是自然排序对元素进行排序的

    • 自然排序,就是让元素所属的类实现Comparable接口,重写compareTo(To)方法

    • 重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写

    学生类

    public class Student implements Comparable<Student> {
        private String name;
        private int age;
    ​
        public Student(String name, int age) {
            this.name = name;
            this.age = 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;
        }
    ​
        public Student() {
        }
    ​
        @Override
        public int compareTo(Student o) {
            //return 0;//只插入一条 默认为两个对象一样
            //return 1;//正数 升序
            //return -1;//负数降序
            //按照年龄从小到大排序
            int num = this.age - o.age;
            int num2 = num==0?name.compareTo(o.name):num;
            return num2;
        }
    ​
    }

     

    测试类

    public class TreeSetDemo {
        public static void main(String[] args) {
            //创建集合对象
            TreeSet<Student> ts = new TreeSet<>();
    ​
            //创建学生对象
            Student s1 = new Student("张三",20);
            Student s2 = new Student("李四",22);
            Student s3 = new Student("王五",21);
            Student s4 = new Student("李六",25);
    ​
            Student s5 = new Student("歪把七",25);
            Student s6 = new Student("歪把七",25);
    ​
            //添加到集合中
            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());
            }
        }
    }

    1.9 比较器排序Comparator的使用

    • 存储学生对象并遍历,创建TreeSet集合使用带参构造方法

    • 要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序

    结论

    • 用TreeSet集合存储自定义对象,带参构造方法使用的是比较器排序对元素进行排序的

    • 比较器排序,就是让集合构造方法接收Comparator的实现类对象,重写compare(T o,T o)方法

    • 重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写

    学生实体类

    public class Student {
        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;
        }
    ​
        public Student() {
        }
    ​
        public Student(String name, int age) {
            this.name = name;
            this.age = age;
        }
    }

     

    测试类

    public class TreeSetDemo {
        public static void main(String[] args) {
            //创建集合对象
            TreeSet<Student> ts = new TreeSet<>(new Comparator<Student>() {
                @Override
                public int compare(Student s1, Student s2) {
                    int num = s1.getAge() - s2.getAge();
                    int num2 = num==0? s1.getName().compareTo(s2.getName()):num;
                    return num2;
                }
            });
    ​
            //创建学生对象
            Student s1 = new Student("张三",20);
            Student s2 = new Student("李四",22);
            Student s3 = new Student("王五",21);
            Student s4 = new Student("李六",25);
    ​
            Student s5 = new Student("歪把七",25);
            Student s6 = new Student("歪把七",25);
    ​
            //添加到集合中
            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());
            }
    ​
    ​
        }
    }

    案例: 成绩排序

    需求:用TreeSet集合存储多个学生信息(姓名、语文成绩、数学成绩),并遍历该集合

    要求:按照总分从高到底出现

    思路:

    ① 定义学生类

    ② 创建TreeSet集合对象,通过比较器排序进行排序

    ③ 创建学生对象

    ④把学生对象添加到集合

    ⑤ 遍历集合

    学生实体类

    public class Student {
        private String name;
        private int chinese;
        private int math;
    ​
        public Student() {
        }
    ​
        public Student(String name, int chinese, int math) {
            this.name = name;
            this.chinese = chinese;
            this.math = math;
        }
    ​
        public String getName() {
            return name;
        }
    ​
        public void setName(String name) {
            this.name = name;
        }
    ​
        public int getChinese() {
            return chinese;
        }
    ​
        public void setChinese(int chinese) {
            this.chinese = chinese;
        }
    ​
        public int getMath() {
            return math;
        }
    ​
        public void setMath(int math) {
            this.math = math;
        }
        public int getSum(){
            return this.chinese + this.math;
        }
    }

     

    测试类

    public class TreeSetDemo {
        public static void main(String[] args) {
            //创建TreeSet集合对象,通过比较器排序进行排序
            TreeSet<Student> ts = new TreeSet<>(new Comparator<Student>() {
                @Override
                public int compare(Student s1, Student s2) {
                    //主要条件
                    int num =s1.getSum() - s2.getSum();
                    //次要条件
                    int num2 = num == 0 ? s1.getChinese()-s2.getChinese():num;
                    int num3 = num2 == 0 ? s1.getName().compareTo(s2.getName()):num2;
                    return num3;
                }
            });
    ​
            //创建学生对象
            Student s1 = new Student("张三",98,87);
            Student s2 = new Student("李四",94,92);
            Student s3 = new Student("王五",77,95);
            Student s4 = new Student("李六",90,83);
            Student s5 = new Student("麻子七",70,99);
    ​
            Student s6 = new Student("崴脚八",75,94);
    ​
            //添加到数组
            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.getChinese()+","+s.getMath()+","+s.getSum());
            }
        }
    }

    案例: 不重复的随机数

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

    思路:

    ① 创建Set集合对象

    ② 创建随机数对象

    ③ 判断集合的长度是不是小于10

    是:产生一个随机数,添加到集合

    回到③继续

    ④ 遍历集合

    测试类

    public class SetDemo {
        public static void main(String[] args) {
            //创建一个set集合
            //不排序
            //Set<Integer> set = new HashSet<>();
            //排序
            Set<Integer> set = new TreeSet<>();
            //创建一个随机数对象
            Random r = new Random();
    ​
            //判断集合的长度是否小于10
            while (set.size()<10){
                //产生一个随机数,添加到集合
                int number = r.nextInt(20)+1;
                set.add(number);
            }
    ​
            //遍历集合
            for (Integer i : set){
                System.out.println(i);
            }
        }
    }

     

  • 相关阅读:
    Android Material Design控件使用(2)——FloatButton TextInputEditText TextInputLayout 按钮和输入框
    HbuilderX 常用快捷键
    Android Material Design控件使用(一)——ConstraintLayout 约束布局
    git 命令行 修改文件 并push(阿里云)
    【http转https】其之二:申请Let's Encrypt颁发SSL证书
    git: fatal: Could not read from remote repository
    Android Vector曲折的兼容之路
    Gradle Build速度加快终极方法(android studio)
    android studio 更新 Gradle错误解决方法(Gradle sync failed)
    开发Android必知的工具
  • 原文地址:https://www.cnblogs.com/DiaoStudy/p/13657585.html
Copyright © 2011-2022 走看看