大数据之路week02 Collection 集合体系收尾(Set)
Posted Xiaohu_BigData
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了大数据之路week02 Collection 集合体系收尾(Set)相关的知识,希望对你有一定的参考价值。
1、Set集合(理解)
(1)Set集合的特点
无序,唯一。
(2)HashSet集合(掌握)
A: 底层数据结构是哈希表(是一个元素为链表的数组)
B: 哈希表底层依赖两个方法: hashCode() 和 equals()
执行顺序:
首先比较哈希值是否相同
相同:继续执行equals()方法
返回true:元素重复了,不添加
返回false:直接把元素添加到集合
不同:就直接把元素添加到集合
1、人的类
1 package com.wyh.hashSet; 2 3 /** 4 * @author WYH 5 * @version 2019年11月17日 上午9:21:02 6 */ 7 public class Person { 8 private String name; 9 private int age; 10 11 public Person(String name, int age) { 12 super(); 13 this.name = name; 14 this.age = age; 15 } 16 public Person() { 17 super(); 18 // TODO Auto-generated constructor stub 19 } 20 21 public String getName() { 22 return name; 23 } 24 public void setName(String name) { 25 this.name = name; 26 } 27 public int getAge() { 28 return age; 29 } 30 public void setAge(int age) { 31 this.age = age; 32 } 33 34 //重写hashCode方法和equals方法 35 @Override 36 public int hashCode() { 37 final int prime = 31; 38 int result = 1; 39 result = prime * result + age; 40 result = prime * result + ((name == null) ? 0 : name.hashCode()); 41 return result; 42 } 43 @Override 44 public boolean equals(Object obj) { 45 if (this == obj) 46 return true; 47 if (obj == null) 48 return false; 49 if (getClass() != obj.getClass()) 50 return false; 51 Person other = (Person) obj; 52 if (age != other.age) 53 return false; 54 if (name == null) { 55 if (other.name != null) 56 return false; 57 } else if (!name.equals(other.name)) 58 return false; 59 return true; 60 } 61 62 63 }
2、测试类:
1 package com.wyh.hashSet; 2 3 import java.util.HashSet; 4 5 /** 6 * @author WYH 7 * @version 2019年11月17日 上午9:21:16 8 */ 9 public class HashSetDemo01 { 10 public static void main(String[] args) { 11 //创建HashSet集合 12 HashSet<Person> hs = new HashSet<Person>(); 13 14 //创建Person类 15 Person p1 = new Person("小虎",22); 16 Person p2 = new Person("小强",23); 17 Person p3 = new Person("小虎",22); 18 Person p4 = new Person("小美",21); 19 Person p5 = new Person("小雪",21); 20 21 //将对象添加到HashSet中去 22 hs.add(p1); 23 hs.add(p2); 24 hs.add(p3); 25 hs.add(p4); 26 hs.add(p5); 27 28 29 //遍历 30 for(Person p : hs) { 31 System.out.println(p.getName()+"---"+p.getAge()); 32 33 34 } 35 } 36 37 }
3、如下图,如果不重写hashCode()方法和equals()方法,运行结果,可以运行不报错,但是重复的元素也加入了。
4、重写后:
C:如何保证元素的唯一性呢?
由hashCode()和equals()保证的(如下图,流程)
D:开发的时候,代码非常的简单,自动生成即可。
E:HashSet存储字符串并遍历
1 package com.wyh.set; 2 3 import java.util.HashSet; 4 5 /** 6 * @author WYH 7 * @version 2019年11月16日 下午7:42:24 8 * 9 * HashSet在存储字符串的时候,为什么只存储相同的字符串只存储一个呢? 10 * 通过查看add方法的源码,我们发现这个方法的底层方法是依赖两个方法,hashCode()和equals() 11 * 12 * 13 */ 14 public class HashSetDemo01 { 15 public static void main(String[] args) { 16 HashSet<String> hs = new HashSet<String>(); 17 18 hs.add("Hello"); 19 hs.add("World"); 20 hs.add("Java"); 21 hs.add("World"); 22 23 for(String s : hs) { 24 System.out.println(s); 25 } 26 27 } 28 29 }
F:HashSet存储自定义对象并遍历(对象的成员变量值相同即为同一个元素)
(3)TreeSet集合
A:底层数据结构是红黑树(是一个自平衡的二叉树)
B: 保证元素的排序方式
a: 自然排序(元素具备比较性)
让元素所属的类实现Comparable接口(难点,需求会给出主要条件,但是需要我们分析次要条件,例如 需求是根据年龄的长度进行排序,但是我们还要考虑姓名的长度和内容)
学生类:
1 package com.wyh.treeSet; 2 3 /** 4 * @author WYH 5 * @version 2019年11月17日 上午11:13:45 6 */ 7 public class Student2 implements Comparable<Student2>{ 8 private String name; 9 private int age; 10 public Student2(String name, int age) { 11 super(); 12 this.name = name; 13 this.age = age; 14 } 15 public Student2() { 16 super(); 17 // TODO Auto-generated constructor stub 18 } 19 public String getName() { 20 return name; 21 } 22 public void setName(String name) { 23 this.name = name; 24 } 25 public int getAge() { 26 return age; 27 } 28 public void setAge(int age) { 29 this.age = age; 30 } 31 @Override 32 public int compareTo(Student2 s) { 33 int num = this.name.length() - s.name.length(); 34 //次要条件1 姓名长度一样,内容不一定一样 35 int num2 = num == 0 ? (this.name.compareTo(s.name)) : num; 36 //次要条件2 姓名长度和内容一样,年龄不一定一样 37 int num3 = num2 == 0 ? this.age - s.age : num2; 38 return num3; 39 40 } 41 42 43 44 45 }
测试类:
如果不重写自然排序方法,就会报错,因为没有给定如何排序,也没有保证唯一性
// java.lang.ClassCastException: com.wyh.treeSet.Student cannot be cast to
// java.lang.Comparable
1 package com.wyh.treeSet; 2 3 import java.util.TreeSet; 4 5 /** 6 * @author WYH 7 * @version 2019年11月17日 下午2:27:13 8 * 9 * 根据年龄的长度进行排序 10 */ 11 public class TreeSetDemo03 { 12 public static void main(String[] args) { 13 TreeSet<Student2> ts = new TreeSet<Student2>(); 14 15 // 创建学生对象 16 Student2 s1 = new Student2("王友虎", 22); 17 Student2 s2 = new Student2("赵以浩", 24); 18 Student2 s3 = new Student2("齐博源", 21); 19 Student2 s4 = new Student2("李先锋", 23); 20 Student2 s5 = new Student2("李宏灿", 22); 21 Student2 s6 = new Student2("薛长城", 23); 22 Student2 s7 = new Student2("黄天祥", 24); 23 Student2 s8 = new Student2("王友虎", 23); 24 25 // 添加到TreeSet中 26 ts.add(s1); 27 ts.add(s2); 28 ts.add(s3); 29 ts.add(s4); 30 ts.add(s5); 31 ts.add(s6); 32 ts.add(s7); 33 ts.add(s8); 34 35 // 遍历 36 // 如果不重写自然排序方法,就会报错,因为没有给定如何排序,也没有保证唯一性 37 // java.lang.ClassCastException: com.wyh.treeSet.Student cannot be cast to 38 // java.lang.Comparable 39 for (Student2 s : ts) { 40 System.out.println(s.getName() + "---" + s.getAge()); 41 } 42 43 } 44 45
b: 比较器排序(集合具备比较性)
让集合构造方法接收Comparator的实现类对象(但是我们一般用匿名内部类的方式实现)
方式1、我们不用内部类的方式实现:
定义一个类实现Comparator<T> 接口,重写compare方法:
1 package com.wyh.treeSet2; 2 3 import java.util.Comparator; 4 5 /** 6 * @author WYH 7 * @version 2019年11月17日 下午2:48:22 8 */ 9 public class MyComparator implements Comparator<Student2> { 10 11 @Override 12 public int compare(Student2 s1, Student2 s2) { 13 int num = s1.getName().length() - s2.getName().length(); 14 int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num; 15 int num3 = num2 == 0 ? s1.getAge() - s2.getAge() : num2; 16 return num3; 17 } 18 19 20 21 }
测试类:
1 package com.wyh.treeSet2; 2 3 import java.util.Comparator; 4 import java.util.TreeSet; 5 6 /** 7 * @author WYH 8 * @version 2019年11月17日 下午2:27:13 9 * 10 * 根据年龄的长度进行排序 11 */ 12 public class TreeSetDemo03 { 13 public static void main(String[] args) { 14 // TreeSet<Student2> ts = new TreeSet<Student2>(); 15 TreeSet<Student2> ts = new TreeSet<Student2>(new MyComparator()); 16 17 //如果一个方法的参数是接口,那么真正要的是实现这个接口的实现类 18 //匿名内部类可以是实现 19 /* TreeSet<Student2> ts = new TreeSet<Student2>(new Comparator<Student2>(){ 20 @Override 21 public int compare(Student2 s1, Student2 s2) { 22 int num = s1.getName().length() - s2.getName().length(); 23 int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num; 24 int num3 = num2 == 0 ? s1.getAge() - s2.getAge() : num2; 25 return num3; 26 } 27 });*/ 28 29 // 创建学生对象 30 Student2 s1 = new Student2("王友虎", 22); 31 Student2 s2 = new Student2("赵以浩", 24); 32 Student2 s3 = new Student2("齐博源", 21); 33 Student2 s4 = new Student2("李先锋", 23); 34 Student2 s5 = new Student2("李宏灿", 22); 35 Student2 s6 = new Student2("薛长城", 23); 36 Student2 s7 = new Student2("黄天祥", 24); 37 Student2 s8 = new Student2("王友虎", 23); 38 39 // 添加到TreeSet中 40 ts.add(s1); 41 ts.add(s2); 42 ts.add(s3); 43 ts.add(s4); 44 ts.add(s5); 45 ts.add(s6); 46 ts.add(s7); 47 ts.add(s8); 48 49 // 遍历 50 // 如果不重写自然排序方法,就会报错,因为没有给定如何排序,也没有保证唯一性 51 // java.lang.ClassCastException: com.wyh.treeSet.Student cannot be cast to 52 // java.lang.Comparable 53 for (Student2 s : ts) { 54 System.out.println(s.getName() + "---" + s.getAge()); 55 } 56 57 } 58 59 }
方式2、用匿名内部类的方式实现:
1 package com.wyh.treeSet2; 2 3 import java.util.Comparator; 4 import java.util.TreeSet; 5 6 /** 7 * @author WYH 8 * @version 2019年11月17日 下午2:27:13 9 * 10 * 根据年龄的长度进行排序 11 */ 12 public class TreeSetDemo03 { 13 public static void main(String[] args) { 14 // TreeSet<Student2> ts = new TreeSet<Student2>(); 15 // TreeSet<Student2> ts = new TreeSet<Student2>(new MyComparator()); 16 17 //如果一个方法的参数是接口,那么真正要的是实现这个接口的实现类 18 //匿名内部类可以是实现 19 TreeSet<Student2> ts = new TreeSet<Student2>(new Comparator<Student2>(){ 20 @Override 21 public int compare(Student2 s1, Student2 s2) { 22 int num = s1.getName().length() - s2.getName().length(); 23 int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num; 24 int num3 = num2 == 0 ? s1.getAge() - s2.getAge() : num2; 25 return num3; 26 } 27 }); 28 29 // 创建学生对象 30 Student2 s1 = new Student2("王友虎", 22); 31 Student2 s2 = new Student2("赵以浩", 24); 32 Student2 s3 = new Student2("齐博源", 21); 33 Student2 s4 = new Student2("李先锋", 23); 34 Student2 s5 = new Student2("李宏灿", 22); 35 Student2 s6 = new Student2("薛长城", 23); 36 Student2 s7 = new Student2("黄天祥", 24); 37 Student2 s8 = new Student2("王友虎", 23); 38 39 // 添加到TreeSet中 40 ts.add(s1); 41 ts.add(s2); 42 ts.add(s3); 43 ts.add(s4); 44 ts.add(s5); 45 ts.add(s6); 46 ts.add(s7); 47 ts.add(s8); 48 49 // 遍历 50 // 如果不重写自然排序方法,就会报错,因为没有给定如何排序,也没有保证唯一性 51 // java.lang.ClassCastException: com.wyh.treeSet.Student cannot be cast to 52 // java.lang.Comparable 53 for (Student2 s : ts) { 54 System.out.println(s.getName() + "---" + s.getAge()); 55 } 56 57 } 58 59 }
(4)案例:
A: 获取无重复的随机数(HashSet实现)
1 package com.wyh.HashSet_random; 2 3 import java.util.Arrays; 4 import java.util.HashSet; 5 import java.util.Random; 6 7 /** 8 * @author WYH 9 * @version 2019年11月17日 下午3:14:10 10 * 11 * 实现10个1-20的随机数 12 * 13 * 14 * 15 */ 16 public class HashSet_random_Demo { 17 public static void main(String[] args) { 18 //创建随机数对象 19 Random r = new Random(); 20 21 //创建HashSet集合 22 HashSet<Integer> hs = new HashSet<Integer>(); 23 24 //判断元素是否小于10 25 while(hs.size()<10) { 26 int num = r.nextInt(20)+1; 27 hs.add(num); 28 } 29 30 Object[] obj = hs.toArray(); 31 Arrays.sort(obj); 32 33 //遍历集合 34 for(Object i : obj) { 35 System.out.println(i); 36 } 37 } 38 }
B: 键盘录入学生按照总分从搞到底输出(TreeSet且用匿名内部类实现)
1 package TreeSet_Scanner; 2 3 import java.util.Comparator; 4 import java.util.Scanner; 5 import java.util.TreeSet; 6 7 8 /** 9 * @author WYH 10 * @version 2019年11月17日 下午3:25:25 11 * 12 * 键盘录入5个学生信息,并且按照总分高低排序 13 */ 14 public class大数据之路week01--自学之集合_1大数据之路week01--自学之集合_2(Iterator迭代器)