java 集合2
1.Set集合
1.1Set集合概述和特點【應用】
- Set集合的特點
- 元素存取無序
- 沒有索引、只能通過迭代器或增強for循環遍歷
- 不能存儲重復元素
- Set集合的基本使用
public class SetDemo {
public static void main(String[] args) {
//創建集合對象
Set<String> set = new HashSet<String>();
//添加元素
set.add("hello");
set.add("world");
set.add("java");
//不包含重復元素的集合
set.add("world");
//遍歷
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 Student() { } 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; } @Override public int hashCode() { return 0; } }- 測試類
public class HashDemo { public static void main(String[] args) { //創建學生對象 Student s1 = new Student("林青霞",30); //同一個對象多次調用hashCode()方法返回的哈希值是相同的 System.out.println(s1.hashCode()); //1060830840 System.out.println(s1.hashCode()); //1060830840 System.out.println("--------"); Student s2 = new Student("林青霞",30); //默認情況下,不同對象的哈希值是不相同的 //通過方法重寫,可以實現不同對象的哈希值是相同的 System.out.println(s2.hashCode()); //2137211482 System.out.println("--------"); System.out.println("hello".hashCode()); //99162322 System.out.println("world".hashCode()); //113318802 System.out.println("java".hashCode()); //3254818 System.out.println("world".hashCode()); //113318802 System.out.println("--------"); System.out.println("重地".hashCode()); //1179395 System.out.println("通話".hashCode()); //1179395 } }
1.3HashSet集合概述和特點【應用】
-
HashSet集合的特點
- 底層數據結構是哈希表
- 對集合的迭代順序不作任何保證,也就是說不保證存儲和取出的元素順序一致
- 沒有帶索引的方法,所以不能使用普通for循環遍歷
- 由于是Set集合,所以是不包含重復元素的集合
-
HashSet集合的基本使用
public class HashSetDemo01 { public static void main(String[] args) { //創建集合對象 HashSet<String> hs = new HashSet<String>(); //添加元素 hs.add("hello"); hs.add("world"); hs.add("java"); hs.add("world"); //遍歷 for(String s : hs) { System.out.println(s); } } }
1.4HashSet集合保證元素唯一性源碼分析【理解】
-
HashSet集合保證元素唯一性的原理
? 1.根據對象的哈希值計算存儲位置
? 如果當前位置沒有元素則直接存入
? 如果當前位置有元素存在,則進入第二步
? 2.當前元素的元素和已經存在的元素比較哈希值
? 如果哈希值不同,則將當前元素進行存儲
? 如果哈希值相同,則進入第三步
? 3.通過equals()方法比較兩個元素的內容
? 如果內容不相同,則將當前元素進行存儲
? 如果內容相同,則不存儲當前元素
-
HashSet集合保證元素唯一性的圖解
![image]()
1.5常見數據結構之哈希表【理解】

1.6HashSet集合存儲學生對象并遍歷【應用】
-
案例需求
- 創建一個存儲學生對象的集合,存儲多個學生對象,使用程序實現在控制臺遍歷該集合
- 要求:學生對象的成員變量值相同,我們就認為是同一個對象
-
代碼實現
-
學生類
public class Student { private String name; private int age; public Student() { } 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; } @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 HashSetDemo02 { public static void main(String[] args) { //創建HashSet集合對象 HashSet<Student> hs = new HashSet<Student>(); //創建學生對象 Student s1 = new Student("林青霞", 30); Student s2 = new Student("張曼玉", 35); Student s3 = new Student("王祖賢", 33); Student s4 = new Student("王祖賢", 33); //把學生添加到集合 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.7LinkedHashSet集合概述和特點【應用】
-
LinkedHashSet集合特點
- 哈希表和鏈表實現的Set接口,具有可預測的迭代次序
- 由鏈表保證元素有序,也就是說元素的存儲和取出順序是一致的
- 由哈希表保證元素唯一,也就是說沒有重復的元素
-
LinkedHashSet集合基本使用
public class LinkedHashSetDemo { public static void main(String[] args) { //創建集合對象 LinkedHashSet<String> linkedHashSet = new LinkedHashSet<String>(); //添加元素 linkedHashSet.add("hello"); linkedHashSet.add("world"); linkedHashSet.add("java"); linkedHashSet.add("world"); //遍歷集合 for(String s : linkedHashSet) { System.out.println(s); } } }
2.Set集合排序
2.1TreeSet集合概述和特點【應用】
-
TreeSet集合概述
- 元素有序,可以按照一定的規則進行排序,具體排序方式取決于構造方法
- TreeSet():根據其元素的自然排序進行排序
- TreeSet(Comparator comparator) :根據指定的比較器進行排序
- 沒有帶索引的方法,所以不能使用普通for循環遍歷
- 由于是Set集合,所以不包含重復元素的集合
- 元素有序,可以按照一定的規則進行排序,具體排序方式取決于構造方法
-
TreeSet集合基本使用
public class TreeSetDemo01 { public static void main(String[] args) { //創建集合對象 TreeSet<Integer> ts = new TreeSet<Integer>(); //添加元素 ts.add(10); ts.add(40); ts.add(30); ts.add(50); ts.add(20); ts.add(30); //遍歷集合 for(Integer i : ts) { System.out.println(i); } } }
2.2自然排序Comparable的使用【應用】
-
案例需求
- 存儲學生對象并遍歷,創建TreeSet集合使用無參構造方法
- 要求:按照年齡從小到大排序,年齡相同時,按照姓名的字母順序排序
-
實現步驟
- 用TreeSet集合存儲自定義對象,無參構造方法使用的是自然排序對元素進行排序的
- 自然排序,就是讓元素所屬的類實現Comparable接口,重寫compareTo(T o)方法
- 重寫方法時,一定要注意排序規則必須按照要求的主要條件和次要條件來寫
-
代碼實現
-
學生類
public class Student implements Comparable<Student> { private String name; private int age; public Student() { } 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; } @Override public int compareTo(Student s) { // return 0; // return 1; // return -1; //按照年齡從小到大排序 int num = this.age - s.age; // int num = s.age - this.age; //年齡相同時,按照姓名的字母順序排序 int num2 = num==0?this.name.compareTo(s.name):num; return num2; } } -
測試類
public class TreeSetDemo02 { public static void main(String[] args) { //創建集合對象 TreeSet<Student> ts = new TreeSet<Student>(); //創建學生對象 Student s1 = new Student("xishi", 29); Student s2 = new Student("wangzhaojun", 28); Student s3 = new Student("diaochan", 30); Student s4 = new Student("yangyuhuan", 33); Student s5 = new Student("linqingxia",33); Student s6 = new Student("linqingxia",33); //把學生添加到集合 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()); } } }
-
2.3比較器排序Comparator的使用【應用】
-
案例需求
- 存儲學生對象并遍歷,創建TreeSet集合使用帶參構造方法
- 要求:按照年齡從小到大排序,年齡相同時,按照姓名的字母順序排序
-
實現步驟
- 用TreeSet集合存儲自定義對象,帶參構造方法使用的是比較器排序對元素進行排序的
- 比較器排序,就是讓集合構造方法接收Comparator的實現類對象,重寫compare(T o1,T o2)方法
- 重寫方法時,一定要注意排序規則必須按照要求的主要條件和次要條件來寫
-
代碼實現
-
學生類
public class Student { private String name; private int age; public Student() { } 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 class TreeSetDemo { public static void main(String[] args) { //創建集合對象 TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() { @Override public int compare(Student s1, Student s2) { //this.age - s.age //s1,s2 int num = s1.getAge() - s2.getAge(); int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num; return num2; } }); //創建學生對象 Student s1 = new Student("xishi", 29); Student s2 = new Student("wangzhaojun", 28); Student s3 = new Student("diaochan", 30); Student s4 = new Student("yangyuhuan", 33); Student s5 = new Student("linqingxia",33); Student s6 = new Student("linqingxia",33); //把學生添加到集合 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()); } } }
-
2.4成績排序案例【應用】
-
案例需求
- 用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<Student>(new Comparator<Student>() { @Override public int compare(Student s1, Student s2) { // int num = (s2.getChinese()+s2.getMath())-(s1.getChinese()+s1.getMath()); //主要條件 int num = s2.getSum() - s1.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, 100); Student s2 = new Student("張曼玉", 95, 95); Student s3 = new Student("王祖賢", 100, 93); Student s4 = new Student("柳巖", 100, 97); Student s5 = new Student("風清揚", 98, 98); Student s6 = new Student("左冷禪", 97, 99); // Student s7 = new Student("左冷禪", 97, 99); Student s7 = new Student("趙云", 97, 99); //把學生對象添加到集合 ts.add(s1); ts.add(s2); ts.add(s3); ts.add(s4); ts.add(s5); ts.add(s6); ts.add(s7); //遍歷集合 for (Student s : ts) { System.out.println(s.getName() + "," + s.getChinese() + "," + s.getMath() + "," + s.getSum()); } } }
-
2.5不重復的隨機數案例【應用】
-
案例需求
- 編寫一個程序,獲取10個1-20之間的隨機數,要求隨機數不能重復,并在控制臺輸出
-
代碼實現
public class SetDemo { public static void main(String[] args) { //創建Set集合對象 // Set<Integer> set = new HashSet<Integer>(); Set<Integer> set = new TreeSet<Integer>(); //創建隨機數對象 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); } } }
3.泛型
3.1泛型概述和好處【理解】
-
泛型概述
? 是JDK5中引入的特性,它提供了編譯時類型安全檢測機制,該機制允許在編譯時檢測到非法的類型
它的本質是參數化類型,也就是說所操作的數據類型被指定為一個參數。一提到參數,最熟悉的就是定義方法時有形參,然后調用此方法時傳遞實參。那么參數化類型怎么理解呢?顧名思義,就是將類型由原來的具體的類型參數化,然后在使用/調用時傳入具體的類型。這種參數類型可以用在類、方法和接口中,分別被稱為泛型類、泛型方法、泛型接口
-
泛型定義格式
- <類型>:指定一種類型的格式。這里的類型可以看成是形參
- <類型1,類型2…>:指定多種類型的格式,多種類型之間用逗號隔開。這里的類型可以看成是形參
- 將來具體調用時候給定的類型可以看成是實參,并且實參的類型只能是引用數據類型
-
泛型的好處
- 把運行時期的問題提前到了編譯期間
- 避免了強制類型轉換
3.2泛型類【應用】
-
定義格式
修飾符 class 類名<類型> { } -
示例代碼
-
泛型類
public class Generic<T> { private T t; public T getT() { return t; } public void setT(T t) { this.t = t; } } -
測試類
public class GenericDemo { public static void main(String[] args) { Generic<String> g1 = new Generic<String>(); g1.setT("林青霞"); System.out.println(g1.getT()); Generic<Integer> g2 = new Generic<Integer>(); g2.setT(30); System.out.println(g2.getT()); Generic<Boolean> g3 = new Generic<Boolean>(); g3.setT(true); System.out.println(g3.getT()); } }
-
3.3泛型方法【應用】
-
定義格式
修飾符 <類型> 返回值類型 方法名(類型 變量名) { } -
示例代碼
-
帶有泛型方法的類
public class Generic { public <T> void show(T t) { System.out.println(t); } } -
測試類
public class GenericDemo { public static void main(String[] args) { Generic g = new Generic(); g.show("林青霞"); g.show(30); g.show(true); g.show(12.34); } }
-
3.4泛型接口【應用】
-
定義格式
修飾符 interface 接口名<類型> { } -
示例代碼
-
泛型接口
public interface Generic<T> { void show(T t); } -
泛型接口實現類
public class GenericImpl<T> implements Generic<T> { @Override public void show(T t) { System.out.println(t); } } -
測試類
public class GenericDemo { public static void main(String[] args) { Generic<String> g1 = new GenericImpl<String>(); g1.show("林青霞"); Generic<Integer> g2 = new GenericImpl<Integer>(); g2.show(30); } }
-
3.5類型通配符【應用】
-
類型通配符的作用
? 為了表示各種泛型List的父類,可以使用類型通配符
-
類型通配符的分類
- 類型通配符:<?>
- List<?>:表示元素類型未知的List,它的元素可以匹配任何的類型
- 這種帶通配符的List僅表示它是各種泛型List的父類,并不能把元素添加到其中
- 類型通配符上限:<? extends 類型>
- List<? extends Number>:它表示的類型是Number或者其子類型
- 類型通配符下限:<? super 類型>
- List<? super Number>:它表示的類型是Number或者其父類型
- 類型通配符:<?>
-
類型通配符的基本使用
public class GenericDemo { public static void main(String[] args) { //類型通配符:<?> List<?> list1 = new ArrayList<Object>(); List<?> list2 = new ArrayList<Number>(); List<?> list3 = new ArrayList<Integer>(); System.out.println("--------"); //類型通配符上限:<? extends 類型> // List<? extends Number> list4 = new ArrayList<Object>(); List<? extends Number> list5 = new ArrayList<Number>(); List<? extends Number> list6 = new ArrayList<Integer>(); System.out.println("--------"); //類型通配符下限:<? super 類型> List<? super Number> list7 = new ArrayList<Object>(); List<? super Number> list8 = new ArrayList<Number>(); // List<? super Number> list9 = new ArrayList<Integer>(); } }
4.可變參數
4.1可變參數【應用】
-
可變參數介紹
? 可變參數又稱參數個數可變,用作方法的形參出現,那么方法參數個數就是可變的了
-
可變參數定義格式
修飾符 返回值類型 方法名(數據類型… 變量名) { } -
可變參數的注意事項
- 這里的變量其實是一個數組
- 如果一個方法有多個參數,包含可變參數,可變參數要放在最后
-
可變參數的基本使用
public class ArgsDemo01 { public static void main(String[] args) { System.out.println(sum(10, 20)); System.out.println(sum(10, 20, 30)); System.out.println(sum(10, 20, 30, 40)); System.out.println(sum(10,20,30,40,50)); System.out.println(sum(10,20,30,40,50,60)); System.out.println(sum(10,20,30,40,50,60,70)); System.out.println(sum(10,20,30,40,50,60,70,80,90,100)); } // public static int sum(int b,int... a) { // return 0; // } public static int sum(int... a) { int sum = 0; for(int i : a) { sum += i; } return sum; } }
4.2可變參數的使用【應用】
-
Arrays工具類中有一個靜態方法:
- public static
List asList(T... a):返回由指定數組支持的固定大小的列表 - 返回的集合不能做增刪操作,可以做修改操作
- public static
-
List接口中有一個靜態方法:
- public static
List of(E... elements):返回包含任意數量元素的不可變列表 - 返回的集合不能做增刪改操作
- public static
-
Set接口中有一個靜態方法:
- public static
Set of(E... elements) :返回一個包含任意數量元素的不可變集合 - 在給元素的時候,不能給重復的元素
- 返回的集合不能做增刪操作,沒有修改的方法
- public static
-
示例代碼
public class ArgsDemo02 { public static void main(String[] args) { //public static <T> List<T> asList(T... a):返回由指定數組支持的固定大小的列表 // List<String> list = Arrays.asList("hello", "world", "java"); // //// list.add("javaee"); //UnsupportedOperationException //// list.remove("world"); //UnsupportedOperationException // list.set(1,"javaee"); // // System.out.println(list); //public static <E> List<E> of(E... elements):返回包含任意數量元素的不可變列表 // List<String> list = List.of("hello", "world", "java", "world"); // //// list.add("javaee");//UnsupportedOperationException //// list.remove("java");//UnsupportedOperationException //// list.set(1,"javaee");//UnsupportedOperationException // // System.out.println(list); //public static <E> Set<E> of(E... elements) :返回一個包含任意數量元素的不可變集合 // Set<String> set = Set.of("hello", "world", "java","world"); //IllegalArgumentException //Set<String> set = Set.of("hello", "world", "java"); // set.add("javaee");//UnsupportedOperationException // set.remove("world");//UnsupportedOperationException //System.out.println(set); } }

浙公網安備 33010602011771號