ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

【JAVA基础】18 集合2

2020-05-26 16:57:48  阅读:217  来源: 互联网

标签:JAVA name 18 age list add 集合 public TreeSet


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循环是否可以在遍历的过程中删除

标签:JAVA,name,18,age,list,add,集合,public,TreeSet
来源: https://www.cnblogs.com/zoe233/p/12914959.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有