zoukankan      html  css  js  c++  java
  • 【JAVA基础】18 集合2

    1. HashSet存储字符串并遍历

    • Set集合概述及特点

      • 一个不包含重复元素的Collection。

      • set不包含满足 e1.equals(e2) 的元素对 e1 和 e2,并且最多包含一个null元素。
      • Set接口没有特殊方法,完全继承Collection接口中的方法。
      • 只要注意如何保证Set集合的元素唯一
      • 无索引,不可以重复,存取不一致
    • 案例演示

      • HashSet存储字符串并遍历

      • package com.heima.set;
        
        import java.util.HashSet;
        
        public class Demo1_HashSet {
        
            /**
             * @param args
             */
            public static void main(String[] args) {
                HashSet<String> hs = new HashSet<>();
                hs.add("a");
                hs.add("b");
                boolean b1 = hs.add("a");
                System.out.println(b1); //输出false 当存储不成功的时候,返回false
                
                for (String string : hs) {
                    System.out.println(string);
                }
            }
        
        }
        View Code

     

    2. HashSet存储自定义对象保证元素唯一性

    • 案例演示

      • 存储自定义对象,并保证元素唯一性。

      • package com.heima.set;
        
        import java.util.HashSet;
        
        import com.heima.bean.Person;
        
        public class Demo2_HashSet {
        
            /**
             * @param args
             */
            public static void main(String[] args) {
                HashSet<Person> hs = new HashSet<>(); 
                hs.add(new Person("张三", 23)); 
                hs.add(new Person("张三", 23)); 
                hs.add(new Person("李四", 23)); 
                hs.add(new Person("李四", 23)); 
                hs.add(new Person("王五", 23)); 
                hs.add(new Person("赵六", 23));
                
                for (Person person : hs) {
                    System.out.println(person);
                }
                
            }
        
        }
        View Code
    • 重写equals()方法

      • package com.heima.bean;
        
        public class Person {
            private String name;
            private int age;
            public Person() {
                super();
                
            }
            public Person(String name, int age) {
                super();
                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;
            }
            @Override
            public String toString() {
                return "Person [name=" + name + ", age=" + age + "]";
            }
            @Override
            public boolean equals(Object obj) {
                Person p = (Person)obj;
                return this.name.equals(p.getName()) && this.age == p.getAge();
                //return super.equals(obj);
            }
            
            
        }
        重写equals方法后
      • 重写euqals()方法后,并不能保证自定义对象在集合中唯一性
    • 重写hashCode() 和 equals()方法
      • package com.heima.bean;
        
        public class Person {
            private String name;
            private int age;
            public Person() {
                super();
                
            }
            public Person(String name, int age) {
                super();
                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;
            }
            @Override
            public String toString() {
                return "Person [name=" + name + ", age=" + age + "]";
            }
            /*@Override
            public boolean equals(Object obj) {
                Person p = (Person)obj;
                System.out.println("验证equals是否执行");
                return this.name.equals(p.getName()) && this.age == p.getAge();
                
            }
            @Override
            public int hashCode() {
                // 第一种方法:hashCode 返回固定值,每次自定义对象都要与生成的第一个占据了固定值位置的对象比较
                // 由于hashCode相等,继而去调用equals方法。
        //        return 10;
                
                // 第二种方法:String对象的hashCode值和 数值 ,减少equals比较调用次数。
        //        return name.hashCode() + age;
                
                // 第三种方法:优化:
        //        final int NUM = 38;
        //        return name.hashCode() * NUM + age;
        }
        */        
                // 第四种方法:开发时常用,alt+shift+s 自动生成
            @Override
            public int hashCode() {
                final int prime = 31;
                int result = 1;
                result = prime * result + age;
                result = prime * result + ((name == null) ? 0 : name.hashCode());
                return result;
            }
            @Override
            public boolean equals(Object obj) {
                if (this == obj)
                    return true;
                if (obj == null)
                    return false;
                if (getClass() != obj.getClass())
                    return false;
                Person other = (Person) obj;
                if (age != other.age)
                    return false;
                if (name == null) {
                    if (other.name != null)
                        return false;
                } else if (!name.equals(other.name))
                    return false;
                return true;
            }
                
            
            
            
            
        }
        View Code
    • 代码优化

      • 为了减少比较,优化hashCode()代码写法。

      • 最终版就是自动生成即可。

     

    3. HashSet如何保证元素唯一性的原理

    • HashSet原理

      • 我们使用Set集合都是需要去掉重复元素的,如果在存储的时候逐个equals()比较,,效率较低,哈希算法提高了去重复的效率,,降低了使用equals()方法的次数

      • 当HashSet调用add()方法存储对象的时候,,先调用对象的hashCode()方法得到一个哈希值,,然后在集合中查找是否有哈希值相同的对象

        • 如果没有哈希值相同的对象就直接存入集合

        • 如果有哈希值相同的对象,,就和哈希值相同的对象逐个进行equals()比较,比较结果为false就存入, true则不存

    • 将自定义类的对象存入HashSet去重复

      • 类中必须重写hashCode()和equals()方法

      • hashCode():属性相同的对象返回值必须相同,,属性不同的返回值尽量不同(提高效率)

      • equals()::属性相同返回true, 属性不同返回false,返回false的时候存储

     

    4. LinkedHashSet的概述和使用

    • LinkedHashSet的特点

      • 保证存取顺序一致
      • LinkedHashSet底层是链表实现的,是set集合中唯一一个能保证怎么存就怎么取的集合对象
      • 因为是HashSet的子类,所以也是保证元素唯一的,与HashSet的原理一样
    • 案例演示

      • package com.heima.set;
        
        import java.util.LinkedHashSet;
        
        public class Demo3_LinkedHashSet {
        
            /**
             * @param args
             */
            public static void main(String[] args) {
                LinkedHashSet<String> lhs = new LinkedHashSet<>();
                lhs.add("a");
                lhs.add("b");
                lhs.add("b");
                lhs.add("c");
                lhs.add("b");
                lhs.add("a");
                
                for (String string : lhs) {
                    System.out.println(string);  // 输出a b c
                }
            }
        
        }
        View Code


    5. 
    练习

    • 产生10个1-20之间的随机数要求随机数不能重复

    • 案例演示

      • 需求:编写一个程序,获取10个1至20的随机数,要求随机数不能重复。并把最终的随机数输出到控制台。

      • package com.heima.test;
        
        import java.util.HashSet;
        import java.util.Random;
        
        public class Test1 {
        
            /**
             编写一个程序,获取10个1至20的随机数,要求随机数不能重复。并把最终的随机数输出到控制台。
             */
            public static void main(String[] args) {
                HashSet<Integer> hs = new HashSet<>();   //创建集合对象 
                Random r = new Random(); //创建随机数对象
                while(hs.size() < 10) {
                    int num = r.nextInt(20) + 1;
                    hs.add(num);
                }
                        
                for (Integer integer : hs) {
                    System.out.println(integer);
                }
                
            }
        
        }
        View Code
    • 使用Scanner从键盘读取一行输入,去掉其中重复字符, 打印出不同的那些字符

      • package com.heima.test;
        
        import java.util.HashSet;
        import java.util.Scanner;
        
        public class Test2 {
        
            /**
             使用Scanner从键盘读取一行输入,去掉其中重复字符, 打印出不同的那些字符
             */
            public static void main(String[] args) {
                Scanner sc = new Scanner(System.in);
                System.out.println("请输入一行字符串:");
                String line = sc.nextLine();
                char[] arr = line.toCharArray(); // 将字符串转换成字符数组
                
                HashSet<Character> hs = new HashSet<>();
                for (Character character : arr) {
                    hs.add(character);
                }
                
                for (Character character : hs) {
                    System.out.println(character);
                }
            
            }
        
        }
        View Code
    • 将集合中的重复元素去掉

      • package com.heima.test;
        
        import java.util.ArrayList;
        import java.util.LinkedHashSet;
        import java.util.List;
        
        public class Test3 {
            /*
             * 将集合中的重复元素去掉
             */
            public static void main(String[] args) {
                ArrayList<String> list = new ArrayList<>(); 
                list.add("a"); 
                list.add("a"); 
                list.add("a"); 
                list.add("b"); 
                list.add("b"); 
                list.add("b"); 
                list.add("b"); 
                list.add("c"); 
                list.add("c"); 
                list.add("c"); 
                list.add("c");
        
                System.out.println(list);
                System.out.println("去除重复后:");
                getSingle(list);
                System.out.println(list);
            }
            
            /*
             * 将集合中的重复元素去掉
             * 1,void
             * 2,List<String> list
             */
            
            public static void getSingle(List<String> list) {
                LinkedHashSet<String> lhs = new LinkedHashSet<>();
                lhs.addAll(list);           //将list集合中的所有元素添加到lhs
                list.clear();               //清空原集合
                list.addAll(lhs);         //将去除重复的元素添回到list中
            }
            
        }
        View Code

     

    6. TreeSet存储Integer类型的元素并遍历

    • 案例演示

      • TreeSet存储Integer类型的元素并遍历

      • package com.heima.set;
        
        import java.util.TreeSet;
        
        public class Demo4_TreeSet {
        
            /**
            TreeSet集合是用来对元素进行排序的,也可以保证元素的唯一性
             */
            public static void main(String[] args) {
                TreeSet<Integer> ts = new TreeSet<>();
                ts.add(4);
                ts.add(1);
                ts.add(2);
                ts.add(3);
                
                System.out.println(ts);  // 输出[1,2,3,4]
                
            }
        
        }
        View Code

     

    7. TreeSet存储自定义对象

    • 案例演示

      • 存储Person对象

      • package com.heima.bean;
        
        public class Person implements Comparable<Person>{
            private String name;
            private int age;
            public Person() {
                super();
                
            }
            public Person(String name, int age) {
                super();
                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;
            }
            @Override
            public String toString() {
                return "Person [name=" + name + ", age=" + age + "]";
            }
            
            //开发时常用,alt+shift+s 自动生成
            @Override
            public int hashCode() {
                final int prime = 31;
                int result = 1;
                result = prime * result + age;
                result = prime * result + ((name == null) ? 0 : name.hashCode());
                System.out.println(result);
                return result;
            }
            @Override
            public boolean equals(Object obj) {
                if (this == obj)
                    return true;
                if (obj == null)
                    return false;
                if (getClass() != obj.getClass())
                    return false;
                Person other = (Person) obj;
                if (age != other.age)
                    return false;
                if (name == null) {
                    if (other.name != null)
                        return false;
                } else if (!name.equals(other.name))
                    return false;
                return true;
            }
            // control + 1, 点击自动生成重写compareTo方法的样式
            @Override
            public int compareTo(Person o) {
                
                return -1;
            }
                
            
            
            
            
        }
        Person类Comparable接口
      • package com.heima.set;
        
        import java.util.TreeSet;
        
        import com.heima.bean.Person;
        
        public class Demo5_TreeSet {
        
            /**
             * @param args
             */
            public static void main(String[] args) {
                TreeSet<Person> ts = new TreeSet<>();
                ts.add(new Person("Ann",22));
                ts.add(new Person("Bill",23));
                ts.add(new Person("Carolle",21));
                ts.add(new Person("Dell",28));
                
                System.out.println(ts); 
                // 报错,ClassCastException
                // Person类接入 Comparable接口,重写compareTo方法后,按照规则输出
                
                
            }
        
        }
        View Code
    • TreeSet集合是用来对象元素进行排序的,同样他也可以保证元素的唯一
    • 当compareTo方法返回0的时候,集合中只有一个元素
    • 当compareTo方法返回 正整数 的时候,集合会怎么存就怎么取(存取顺序一致)
    • 当compareTo方法返回 负整数 的时候,按照倒序返回

     

    8. TreeSet保证元素唯一和自然排序的原理和图解

    • 画图演示

      • TreeSet保证元素唯一和自然排序的原理和图解

      • 主要条件age,次要条件name
        • @Override
              public int compareTo(Person o) {
                  
                  int num = this.age - o.age;
                  return num == 0 ? this.name.compareTo(o.name): num;
              }
                  

    9. TreeSet存储自定义对象并遍历练习

    • TreeSet存储自定义对象并遍历练习1(按照姓名排序)

      • @Override
            public int compareTo(Person o) {
                int num = this.name.compareTo(o.name);
                return num == 0 ? this.age - o.age : num;
                }
    • TreeSet存储自定义对象并遍历练习2(按照姓名的长度排序)

      • @Override
            public int compareTo(Person o) {
                int length = this.name.length() - o.name.length();
                int num = length == 0 ? this.name.compareTo(o.name) : length;
                return num == 0 ? this.age - o.age : num;
                
            }

    10. TreeSet保证元素唯一和比较器排序的原理及代码实现

    • 案例演示

      • TreeSet保证元素唯一和比较器排序的原理及代码实现

      • package com.heima.set;
        
        import java.util.Comparator;
        import java.util.TreeSet;
        
        public class Demo6_TreeSet {
        
            /**
             TreeSet保证元素唯一和比较器排序的原理及代码实现
             */
            public static void main(String[] args) {
                TreeSet<String> ts = new TreeSet<>(new CompareByLen()); // Comparator<String> cp = new CompareByLen();
                ts.add("aaaaaaaaaaaaaaaa");
                ts.add("wc");
                ts.add("who");
                ts.add("MCGA");
                ts.add("Make China Great Again");
                ts.add("Trump");
                ts.add("piapiapia");
                
                for (String string : ts) {
                    System.out.println(string);
                }
                
            }
        
        }
        
        class CompareByLen implements Comparator<String> {
        
            @Override
            public int compare(String s1, String s2) {
                // 按照字符串的长度进行比较
                int length = s1.length() - s2.length();
                return length == 0 ? s1.compareTo(s2) : length;
            }
            
        }
        View Code
    • TreeSet原理
      • 特点

        • TreeSet是用来排序的,可以指定一个顺序, 对象存入之后会按照指定的顺序排列

      • 使用方式

        • 自然顺序(Comparable)

          • TreeSet类的add()方法中会把存入的对象提升为Comparable类型

          • 调用对象的compareTo()方法和集合中的对象比较

          • 根据compareTo()方法返回的结果进行存储

        • 比较器顺序(Comparator)

          • 创建TreeSet的时候可以制定 一个Comparator

          • 如果传入了Comparator的子类对象,那么TreeSet就会按照比较器中的顺序排序

          • add()方法内部会自动调用Comparator接口中compare()方法排序

          • 调用的对象是compare方法的第一个参数,集合中的对象是compare方法的第二个参数

        • 两种方式的区别

          • TreeSet构造函数什么都不传,默认按照类中Comparable的顺序(没有就报错ClassCastException)

          • TreeSet如果传入Comparator,就优先按照Comparator

    11. 练习

    • 在一个集合中存储了无序并且重复的字符串,定义一个方法,让其有序(字典顺序),而且还不能去除重复

      • package com.heima.test;
        
        import java.util.ArrayList;
        import java.util.Comparator;
        import java.util.List;
        import java.util.TreeSet;
        
        public class Test5 {
        
            /**
            在一个集合中存储了无序并且重复的字符串,定义一个方法,让其有序(字典顺序),而且还不能去除重复
             */
            public static void main(String[] args) {
                ArrayList<String> list = new ArrayList<>(); 
                list.add("ccc"); 
                list.add("ccc"); 
                list.add("aaa"); 
                list.add("aaa"); 
                list.add("bbb"); 
                list.add("ddd");
                list.add("ddd");
        
                sort(list);
                System.out.println(list);
            }
            
            /*
             * 定义方法,排序并保留重复
             * 分析:
             * 1. 创建TreeSet集合对象,因为String本身就具备比较功能,但是重复不会保留,所以我们用 比较器
             * 2. 将list集合中所有的元素添加到TreeSet集合中,对其排序,保留重复
             * 3. 清空list集合
             * 4. 将TreeSet集合中排好序的元素添加到list中
            */
            
            public static void sort(List<String> list) {
                //1. 创建TreeSet集合对象,因为String本身就具备比较功能,但是重复不会保留,所以我们用 比较器
                TreeSet<String> ts = new TreeSet<>(new Comparator<String>() {
        
                    @Override
                    public int compare(String s1, String s2) {  // 这边使用了Comparator的匿名内部类的方法,重写了compare方法
                        int num = s1.compareTo(s2);  // 比较字符串顺序为主要条件
                        return num == 0 ? 1 : num;  // 保留重复数据
                    } });
                
                // 2. 将list集合中所有的元素添加到TreeSet集合中,对其排序,保留重复
                ts.addAll(list);
                
                // 3. 清空list集合
                list.clear();
                
                // 4. 将TreeSet集合中排好序的元素添加到list中
                list.addAll(ts);
            }
        }
        View Code
    • 从键盘接收一个字符串, 程序对其中所有字符进行排序,例如键盘输入: helloitcast程序打印:acehillostt

      • package com.heima.test;
        
        import java.util.ArrayList;
        import java.util.Comparator;
        import java.util.Scanner;
        import java.util.TreeSet;
        
        public class Test6 {
        
            /**
             从键盘接收一个字符串, 程序对其中所有字符进行排序,例如键盘输入: helloitcast程序打印:acehillostt
             */
            public static void main(String[] args) {
                /*
                 * 1. 键盘录入字符串,Scanner
                 * 2. 将字符串转换为字符数组
                 * 3. 定义TreeSet集合,传入比较器对字符排序并保留重复
                 * 4. 遍历字符数组,将每一个字符存储在TreeSet集合中
                 * 5. 遍历TreeSet集合,打印每一个字符
                 */
                Scanner sc = new Scanner(System.in);
                System.out.println("请输入一行字符串:");
                
                String line = sc.nextLine();
                char[] arr = line.toCharArray();
                
                ArrayList<String> list = new ArrayList<>();
                list.add(line);
                
                System.out.println(list);
                
                TreeSet<Character> ts = new TreeSet<>(new Comparator<Character>() {
        
                    @Override
                    public int compare(Character c1, Character c2) {
                        int num = c1.compareTo(c2);
                        return num == 0 ? 1 : num;
                    }
                });
                
                for (char c : arr) {
                    ts.add(c);
                }
                
                for (Character ch : ts) {
                    System.out.print(ch);
                }
                
            }
        
        }
        View Code
    • 程序启动后, 可以从键盘输入接收多个整数, 直到输入quit时结束输入. 把所有输入的整数倒序排列打印

      • package com.heima.test;
        
        import java.util.Comparator;
        import java.util.Scanner;
        import java.util.TreeSet;
        
        public class Test7 {
        
            /**
             程序启动后,可以从键盘输入接收多个整数,直到输入quit时结束输入。
             把所有输入的整数倒序排列打印
             */
            public static void main(String[] args) {
                Scanner sc = new Scanner(System.in);
                System.out.println("请输入整数:");
                
                TreeSet<Integer> ts = new TreeSet<>(new Comparator<Integer>() {
        
                    @Override
                    public int compare(Integer i1, Integer i2) {
                        int num = i2.compareTo(i1);  //自动拆箱
                        return num==0 ? 1: num;
                    }
                }
                        );
                
                while(true) {
                    String line = sc.nextLine();
                    if("quit".equals(line))  //如果字符串常量和变量比较,常量放前面,这样不会出现空指针异常,变量里面可能存储null
                        break;
                    try {
                        int num = Integer.parseInt(line);  //将数字字符串转换成数字
                        ts.add(num);
                        
                    } catch (Exception e) {
                        System.out.println("您录入的数据有误,请输入一个整数");
                    }
                }
                
                
                for (Integer integer : ts) {
                    System.out.println(integer);
                }
                
            }
        
        }
        View Code
    • 键盘录入学生信息按照总分排序后输出在控制台

      • 需求:键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低输出到控制台。

      • package com.heima.test;
        
        import java.util.Comparator;
        import java.util.Scanner;
        import java.util.TreeSet;
        
        import com.heima.bean.Student;
        
        public class Test8 {
        
            /**
             需求:键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低输出到控制台。
             分析:
             1. 定义一个学生类
                 成员变量:姓名,语文成绩,数学成绩,英语成绩,总成绩
                 成员方法:
                     空参构造
                     有参构造(参数:姓名,语文成绩,数学成绩,英语成绩)
                     toString方法:遍历集合中的Student对象,显示属性值
             2. 键盘录入Scanner
             3. 创建TreeSet集合对象,引入比较器,按总成绩从高到低排序
             4. 录入5个学生,所以集合中的学生个数为判断条件,如果size是小于5就进行存储
             5. 将录入的字符串切割,用逗号切割,会返回一个字符串数组,将字符串数组中从第二个元素转换成int数组
             6. 将转换后的结果封装成Studeng对象,将Studeng添加到TreeSet集合中
             7. 遍历TreeSet集合,打印每一个Student对象
        
             */
            public static void main(String[] args) {
                Scanner sc = new Scanner(System.in);
                System.out.println("请输入5个学生成绩格式是:(姓名,语文成绩,数学成绩,英语成绩)");
        
                TreeSet<Student> ts = new TreeSet<>(new Comparator<Student>(
                        ) {
        
                    @Override
                    public int compare(Student s1, Student s2) {
                        int num = s2.getSum() - s1.getSum();//根据学生的总成绩降序排列
                        return num==0 ? 1 : num;
                    }
                });
        
                while(ts.size() < 5) {
                    String line = sc.nextLine();
                    try {
                        String[] arr = line.split(",");
                        int chinese = Integer.parseInt(arr[1]);
                        int math = Integer.parseInt(arr[2]);
                        int english = Integer.parseInt(arr[3]);
                        ts.add(new Student(arr[0],chinese,math,english));
                    } catch (Exception e) {
                        System.out.println("录入格式有误,输入5个学生成绩格式是:(姓名,语文成绩,数学成绩,英语成绩)");
                    }
                }
        
                System.out.println("排序后的学生成绩是:");
                for (Student student : ts) {
                    System.out.println(student);
                }
        
            }
        
        }
        View Code

          

    12. List和Set在for循环,迭代器,增强for循环的小结

    • List

      • 普通for循环, 使用get()逐个获取

      • 调用iterator()方法得到Iterator,使用hasNext()和next()方法

      • 增强for循环,,只要可以使用Iterator的类都可以用

      • Vector集合可以使用Enumeration的hasMoreElements()和nextElement()方法

    • Set

      • 调用iterator()方法得到Iterator,使用hasNext()和next()方法

      • 增强for循环, 只要可以使用Iterator的类都可以用

    • 普通for循环、迭代器、增强for循环是否可以在遍历的过程中删除

  • 相关阅读:
    [渣译文] 使用 MVC 5 的 EF6 Code First 入门 系列:为ASP.NET MVC应用程序实现继承
    [渣译文] 使用 MVC 5 的 EF6 Code First 入门 系列:为ASP.NET MVC应用程序处理并发
    [渣译文] 使用 MVC 5 的 EF6 Code First 入门 系列:为ASP.NET MVC应用程序使用异步及存储过程
    [渣译文] 使用 MVC 5 的 EF6 Code First 入门 系列:为ASP.NET MVC应用程序更新相关数据
    [渣译文] 使用 MVC 5 的 EF6 Code First 入门 系列:为ASP.NET MVC应用程序读取相关数据
    [渣译文] 使用 MVC 5 的 EF6 Code First 入门 系列:为ASP.NET MVC应用程序创建更复杂的数据模型
    [渣译文] 使用 MVC 5 的 EF6 Code First 入门 系列:MVC程序中实体框架的Code First迁移和部署
    [渣译文] 使用 MVC 5 的 EF6 Code First 入门 系列:MVC程序中实体框架的连接恢复和命令拦截
    centos常用命令集
    .NET Best Practices
  • 原文地址:https://www.cnblogs.com/zoe233/p/12914959.html
Copyright © 2011-2022 走看看