集合(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); } } }