17. 集合类 (Set的子类HashSet、LinkedHashSet、TreeSet)

来源:互联网 发布:数据分析测试题 编辑:程序博客网 时间:2024/06/05 16:44

2:Set集合(理解)

       (1)Set集合的特点

              无序,唯一

      (2)HashSet集合(掌握)

它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。

 * 注意:虽然Set集合的元素无序,但是,作为集合来说,它肯定有它自己的存储顺序,

              A:底层数据结构是哈希表(是一个元素为链表的数组)

              B:哈希表底层依赖两个方法:hashCode()和equals()

               执行顺序:

                     首先比较哈希值是否相同

                            相同:继续执行equals()方法

                                          返回true:元素重复了,不添加

                                          返回false:直接把元素添加到集合

                            不同:就直接把元素添加到集合

              C:如何保证元素唯一性的呢?

                     由hashCode()和equals()保证的

              D:开发的时候,代码非常的简单,自动生成即可。

              E:HashSet存储字符串并遍历

public class SetDemo {       publicstatic void main(String[] args) {              //创建集合对象              Set<String>set = new HashSet<String>();              //创建并添加元素              set.add("hello");              set.add("java");              set.add("world");              set.add("java");              set.add("world");              //增强for              for(String s : set) {                     System.out.println(s);              }       }}

              F:HashSet存储自定义对象并遍历(对象的成员变量值相同即为同一个元素)

public class Student {       privateString name;       privateint age;       publicStudent() {              super();       }       publicStudent(String name, int age) {              super();              this.name= name;              this.age= age;       }       publicString getName() {              returnname;       }       publicvoid setName(String name) {              this.name= name;       }       publicint getAge() {              returnage;       }       publicvoid setAge(int age) {              this.age= age;       }       @Override       publicint hashCode() {              finalint prime = 31;              intresult = 1;              result= prime * result + age;              result= prime * result + ((name == null) ? 0 : name.hashCode());              returnresult;       }       @Override       publicboolean equals(Object obj) {              if(this == obj)                     returntrue;              if(obj == null)                     returnfalse;              if(getClass() != obj.getClass())                     returnfalse;              Studentother = (Student) obj;              if(age != other.age)                     returnfalse;              if(name == null) {                     if(other.name != null)                            returnfalse;              }else if (!name.equals(other.name))                     returnfalse;              returntrue;       }       //@Override       //public int hashCode() {       //// return 0;       //// 因为成员变量值影响了哈希值,所以我们把成员变量值相加即可       //// return this.name.hashCode() + this.age;       //// 看下面       //// s1:name.hashCode()=40,age=30       //// s2:name.hashCode()=20,age=50       //// 尽可能的区分,我们可以把它们乘以一些整数       //return this.name.hashCode() + this.age * 15;       //}       //@Override       //public boolean equals(Object obj) {       //// System.out.println(this + "---" + obj);       //if (this == obj) {       //return true;       //}       //if (!(obj instanceof Student)) {       //return false;       //}       //Student s = (Student) obj;       //return this.name.equals(s.name) && this.age == s.age;       //}       //@Override       //public String toString() {       //return "Student [name=" + name + ", age=" + age +"]";       //}}

 * 需求:存储自定义对象,并保证元素的唯一性

 * 要求:如果两个对象的成员变量值都相同,则为同一个元素。

 * 目前是不符合我的要求的:因为我们知道HashSet底层依赖的是hashCode()和equals()方法。

 * 而这两个方法我们在学生类中没有重写,所以,默认使用的是Object类。

 * 这个时候,他们的哈希值是不会一样的,根本就不会继续判断,执行了添加操作。

public class HashSetDemo2 {       publicstatic void main(String[] args) {              //创建集合对象              HashSet<Student>hs = new HashSet<Student>();              //创建学生对象              Students1 = new Student("林青霞",27);              Students2 = new Student("柳岩",22);              Students3 = new Student("王祖贤",30);              Students4 = new Student("林青霞",27);              Students5 = new Student("林青霞",20);              Students6 = new Student("范冰冰",22);              //添加元素              hs.add(s1);              hs.add(s2);              hs.add(s3);              hs.add(s4);              hs.add(s5);              hs.add(s6);              //遍历集合              for(Student s : hs) {                     System.out.println(s.getName()+ "---" + s.getAge());              }       }}

(3)LinkedHashSet

底层数据结构由哈希表和链表组成。

哈希表保证元素的唯一性。

              链表保证元素有素。(存储和取出是一致)

public class LinkedHashSetDemo {       publicstatic void main(String[] args) {              //创建集合对象              LinkedHashSet<String>hs = new LinkedHashSet<String>();              //创建并添加元素              hs.add("hello");              hs.add("world");              hs.add("java");              hs.add("world");              hs.add("java");              //遍历              for(String s : hs) {                     System.out.println(s);              }       }}

      (4)TreeSet集合(保证元素唯一性,保证元素的排序)

              A:底层数据结构是红黑树(是一个自平衡的二叉树)

              B:保证元素的排序方式

                     a:自然排序(元素具备比较性)

                            让元素所属的类实现Comparable(自然排序)接口

                     b:比较器排序(集合具备比较性)

                            让集合构造方法接收Comparator(比较器)的实现类对象

              C:把我们讲过的代码看一遍即可

注意:如果同时有自然排序和比较器排序,以比较器排序为主

public class TreeSetDemo {       publicstatic void main(String[] args) {              //创建集合对象              //自然顺序进行排序              TreeSet<Integer>ts = new TreeSet<Integer>();              //创建元素并添加              //20,18,23,22,17,24,19,18,24              ts.add(20);              ts.add(18);              ts.add(23);              ts.add(22);              ts.add(17);              ts.add(24);              ts.add(19);              ts.add(18);              ts.add(24);              //遍历              for(Integer i : ts) {                     System.out.println(i);              }       }}

       (4)案例:

              A:获取无重复的随机数

 * 分析:

 *             A:创建随机数对象

 *             B:创建一个HashSet集合

 *             C:判断集合的长度是不是小于10

 *                    是:就创建一个随机数添加

 *                    否:不搭理它

 *             D:遍历HashSet集合

public class HashSetDemo {   publicstatic void main(String[] args) {          //创建随机数对象          Randomr = new Random();          //创建一个Set集合          HashSet<Integer>ts = new HashSet<Integer>();          //判断集合的长度是不是小于10          while(ts.size() < 10) {                 intnum = r.nextInt(20) + 1;                 ts.add(num);          }          //遍历Set集合          for(Integer i : ts) {                 System.out.println(i);          }   }}

              B:键盘录入学生按照总分从高到底输出

 * 分析:

 *          A:定义学生类

 *          B:创建一个TreeSet集合

 *          C:总分从高到底如何实现呢?            

 *          D:键盘录入5个学生信息

 *          E:遍历TreeSet集合

public class TreeSetDemo {       publicstatic void main(String[] args) {              //创建一个TreeSet集合              TreeSet<Student>ts = new TreeSet<Student>(new Comparator<Student>() {                     @Override                     publicint compare(Student s1, Student s2) {                            //总分从高到低                            intnum = s2.getSum() - s1.getSum();                            //总分相同的不一定语文相同                            intnum2 = num == 0 ? s1.getChinese() - s2.getChinese() : num;                            //总分相同的不一定数序相同                            intnum3 = num2 == 0 ? s1.getMath() - s2.getMath() : num2;                            //总分相同的不一定英语相同                            intnum4 = num3 == 0 ? s1.getEnglish() - s2.getEnglish() : num3;                            //姓名还不一定相同呢                            intnum5 = num4 == 0 ? s1.getName().compareTo(s2.getName())                                          :num4;                            returnnum5;                     }              });              System.out.println("学生信息录入开始");              //键盘录入5个学生信息              for(int x = 1; x <= 5; x++) {                     Scannersc = new Scanner(System.in);                     System.out.println("请输入第" + x + "个学生的姓名:");                     Stringname = sc.nextLine();                     System.out.println("请输入第" + x + "个学生的语文成绩:");                     StringchineseString = sc.nextLine();                     System.out.println("请输入第" + x + "个学生的数学成绩:");                     StringmathString = sc.nextLine();                     System.out.println("请输入第" + x + "个学生的英语成绩:");                     StringenglishString = sc.nextLine();                     //把数据封装到学生对象中                     Students = new Student();                     s.setName(name);                     s.setChinese(Integer.parseInt(chineseString));                     s.setMath(Integer.parseInt(mathString));                     s.setEnglish(Integer.parseInt(englishString));                     //把学生对象添加到集合                     ts.add(s);              }              System.out.println("学生信息录入完毕");              System.out.println("学习信息从高到低排序如下:");              System.out.println("姓名\t语文成绩\t数学成绩\t英语成绩");              //遍历集合              for(Student s : ts) {                     System.out.println(s.getName()+ "\t" + s.getChinese() + "\t"                                   +s.getMath() + "\t" + s.getEnglish());              }       }}

public class Student {   //姓名   privateString name;   //语文成绩   privateint chinese;   //数学成绩   privateint math;   //英语成绩   privateint english;   publicStudent(String name, int chinese, int math, int english) {          super();          this.name= name;          this.chinese= chinese;          this.math= math;          this.english= english;   }   publicStudent() {          super();   }   publicString getName() {          returnname;   }   publicvoid setName(String name) {          this.name= name;   }   publicint getChinese() {          returnchinese;   }   publicvoid setChinese(int chinese) {          this.chinese= chinese;   }   publicint getMath() {          returnmath;   }   publicvoid setMath(int math) {          this.math= math;   }   publicint getEnglish() {          returnenglish;   }   publicvoid setEnglish(int english) {          this.english= english;   }   publicint getSum() {          return this.chinese + this.math + this.english;   }}

3:Collection集合总结(掌握)

       Collection

              |--List    有序(存储顺序和取出顺序一致),可重复

                     |--ArrayList

                            底层数据结构是数组,查询快,增删慢。

                            线程不安全,效率高

                     |--Vector被ArrayList替代

                            底层数据结构是数组,查询快,增删慢。

                            线程安全,效率低

                     |--LinkedList

                            底层数据结构是链表,查询慢,增删快。

                            线程不安全,效率高

              |--Set     无序(存储顺序和取出顺序不一致),唯一

                     |--HashSet

                            底层数据结构是哈希表。线程不同步,效率高

                            如何保证元素唯一性的呢?

                                   依赖两个方法:hashCode()和equals()

                                   开发中自动生成这两个方法即可

                            |--LinkedHashSet  (存储顺序和取出顺序一致)

                                   底层数据结构是链表和哈希表

                                   由链表保证元素有序

                                   由哈希表保证元素唯一

                     |--TreeSet

                            底层数据结构是红黑树。线程不同步,效率高

                            如何保证元素排序的呢?

                                   自然排序

                                   比较器排序

                            如何保证元素唯一性的呢?

                                   根据比较的返回值是否是0来决定

4:针对Collection集合我们到底使用谁呢?(掌握)

       唯一吗?

              是:Set

                     排序吗?

                            是:TreeSet

                            否:HashSet

              如果你知道是Set,但是不知道是哪个Set,就用HashSet。

              否:List

                     要安全吗?

                            是:Vector

                            否:ArrayList或者LinkedList

                                   查询多:ArrayList

                                   增删多:LinkedList

              如果你知道是List,但是不知道是哪个List,就用ArrayList。

       如果你知道是Collection集合,但是不知道使用谁,就用ArrayList。

       如果你知道用集合,就用ArrayList。

5:在集合中常见的数据结构(掌握)

       ArrayXxx:      底层数据结构是数组,查询快,增删慢

       LinkedXxx:    底层数据结构是链表,查询慢,增删快

       HashXxx:       底层数据结构是哈希表。依赖两个方法:hashCode()和equals()

       TreeXxx:        底层数据结构是二叉树。两种方式排序:自然排序和比较器排序


阅读全文
0 0