一、Collection常用的方法:
Java 集合可分為 Set、List 和 Map 三種體系:
Set:無序、不可重復的集合。
List:有序,可重復的集合。
Map:具有映射關系的集合。
Collection 接口是 List、Set 和 Queue 接口的父接口,
該接口里定義的方法既可用於操作 Set 集合,也可用於操作 List 和 Queue 集合:

import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; public class TestCollections { public static void main(String[] args) { //1. 創建一個 Collection 接口的對象. Collection collection = new ArrayList(); //2. Collection 重要方法說明: /** * 2.1 用於添加元素的: * add() * addAll() */ Person p1 = new Person(); collection.add(p1); collection.add(new Person()); Collection collection2 = new ArrayList(); collection2.add(new Person()); collection2.add(new Person()); collection.addAll(collection2); System.out.println(collection.size()); /** * 2.2 用於訪問集合的方法: * 獲取集合的長度: size() * 對集合進行遍歷的方法: iterator() 可以得到對應的 Iterator 接口對象. * * Iterator: 迭代器 * ①. 獲取 Iterator 接口對象: * ②. 使用 while 循環和 Iterator 對象遍歷集合中的每一個元素. 具體使用 Iterator 接口的 * hasNext() 和 next() 方法. */ Iterator iterator = collection.iterator(); while(iterator.hasNext()){ Object obj = iterator.next(); System.out.println(obj); } /** * 2.3 移除集合中的元素: * remove(): 移除某一個指定的對象. 通過 equals() 方法來判斷要移除的那個元素在集合中是否存在. 以及是否能夠成功移除. * removeAll() * clear(): 使集合中的元素置空. */ // collection.clear(); // boolean result = collection.remove(p1); // System.out.println(result); // // result = collection.removeAll(collection2); // // System.out.println(collection.size()); /** * 2.4 用於檢測集合的方法 * retains() * retainsAll() * isEmpty() */ System.out.println(collection.contains(new Person()));//false System.out.println(collection.contains(p1));//true System.out.println(collection.containsAll(collection2));//true System.out.println(collection.isEmpty()); //false // collection.clear(); System.out.println(collection.isEmpty()); //true /** * 2.5 其他方法 * toArray(): * **T [] toArray(T[]): 涉及到泛型, 后面再說. * * equals(): 比較兩個集合是否相等. * hasCode(): */ Object [] objs = collection.toArray(); System.out.println(objs.length); //4 Person p2 = new Person(); Collection collection3 = new HashSet();//可換ArrayList()試試 collection3.add(p1); collection3.add(p2); Collection collection4 = new HashSet(); collection4.add(p2); collection4.add(p1); System.out.println(collection3.equals(collection4)); /** * 使用增強 for 循環的方式來對集合進行遍歷 */ for(Object obj: collection){ System.out.println(obj); } } } class Person(){}
二、Set、HashSet、LinkedHashSet:
Set 集合不允許包含相同的元素,如果試把兩個相同的元素加入同一個 Set 集合中,則添加操作失敗。
Set 判斷兩個對象是否相同不是使用 == 運算符,而是根據 equals 方法。
注意:
1、當向 HashSet 集合中存入一個元素時,HashSet 會調用該對象的 hashCode() 方法來得到該對象的
hashCode 值, 然后根據 hashCode 值決定該對象在 HashSet 中的存儲位置。
2、如果兩個元素的 equals() 方法返回 true,但它們的 hashCode() 返回值不相等,hashSet 將會
把它們存儲在不同的位置,但依然可以添加成功。
3、HashSet 集合判斷兩個元素相等的標准:兩個對象通過 equals() 方法比較相等,並且兩個對象的
hashCode() 方法返回值也相等。即:如果兩個對象通過 equals() 方法返回 true,這兩個對象的
hashCode 值也應該相同。
重寫 hashCode() 方法的基本原則:
1、在程序運行時,同一個對象多次調用 hashCode() 方法應該返回相同的值。
2、當兩個對象的 equals() 方法比較返回 true 時,這兩個對象的 hashCode() 方法的返回值也應相等。
3、對象中用作 equals() 方法比較的 Field,都應該用來計算 hashCode 值。
另外:
1、LinkedHashSet 是 HashSet 的子類。
2、LinkedHashSet 集合根據元素的 hashCode 值來決定元素的存儲位置,但它同時使用鏈表維護元素的次序,
這使得元素看起來是以插入順序保存的。
3、LinkedHashSet 性能插入性能略低於 HashSet,但在迭代訪問 Set 里的全部元素時有很好的性能。
4、LinkedHashSet 有序但不允許集合元素重復。
import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Set; /** * 1. Set 是 Collection 的子接口 * 2. Set 中不允許存放相同的元素. 判定相同元素的標准是, 兩個對象各調用 equals() 方法, 返回 true * 3. HashSet * 3.1 基本特征: * ①. 不能保證元素的排列順序 * ②. HashSet 不是線程安全的 * ③. 集合元素可以使 null * ④. 對於 HashSet: 如果兩個對象通過 equals() 方法返回 true,這兩個對象的 hashCode 值也應該相同。 * * 4. LinkedHashSet: * 4.1 LinkedHashSet 是 HashSet 的子類 * 4.2 使用鏈表維護元素的次序,這使得元素看起來是以插入順序保存的 * 4.3 LinkedHashSet 不允許集合元素重復 */ public class TestSet { public static void main(String[] args) { Set set = new LinkedHashSet(); //new HashSet(); set.add(null); System.out.println(set.size()); //1 Person p1 = new Person(); set.add(p1); set.add(p1); System.out.println(set.size()); //2 set.add(new Person("AA", 12)); set.add(new Person("AA", 12)); System.out.println(set.size()); //3 set.add(new Person("FF", 13)); Iterator it = set.iterator(); while(it.hasNext()){ System.out.println(it.next()); } } } class Person { // @Override // public boolean equals(Object obj) { // return false; // } 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 Person() { // TODO Auto-generated constructor stub } public Person(String name, int age) { super(); this.name = name; this.age = age; } // private static int init = 0; @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; // return init++; } @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; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]"; } }
三、TreeSet:
TreeSet 是 SortedSet 接口的實現類,TreeSet 可以確保集合元素處於排序狀態。
TreeSet 支持兩種排序方法:自然排序和定制排序。默認情況下,TreeSet 采用自然排序。
排序:
1、TreeSet 會調用集合元素的 compareTo(Object obj) 方法來比較元素之間的大小關系,
然后將集合元素按升序排列。
2、如果試圖把一個對象添加到 TreeSet 時,則該對象的類必須實現 Comparable 接口。
3、實現 Comparable 的類必須實現 compareTo(Object obj) 方法,兩個對象即通過
compareTo(Object obj)方法的返回值來比較大小。
Comparable 的典型實現:
BigDecimal、BigInteger 以及所有的數值型對應的包裝類:按它們對應的數值大小進行比較。
Character: 按字符的 UNICODE 值來進行比較。
Boolean: true 對應的包裝類實例大於 false 對應的包裝類實例。
String: 按字符串中字符的 UNICODE 值進行比較。
Date、Time: 后邊的時間、日期比前面的時間、日期大。
注意:
因為只有相同類的兩個實例才會比較大小,所以向 TreeSet 中添加的應該是同一個類的對象,
當需要把一個對象放入 TreeSet 中,重寫該對象對應的 equals() 方法時,應保證該方法與
compareTo(Object obj) 方法有一致的結果:即如果兩個對象通過 equals() 方法比較返回 true,
則通過 compareTo(Object obj) 方法比較應返回 0.
import java.util.*; /* Set:無序,不可以重復元素。 |--HashSet:數據結構是哈希表。線程是非同步的。 保證元素唯一性的原理:判斷元素的hashCode值是否相同。 如果相同,還會繼續判斷元素的equals方法,是否為true。 |--TreeSet:可以對Set集合中的元素進行排序。 底層數據結構是二叉樹。 保證元素唯一性的依據: compareTo方法return 0. TreeSet排序的第一種方式:讓元素自身具備比較性。 元素需要實現Comparable接口,覆蓋compareTo方法。 也種方式也成為元素的自然順序,或者叫做默認順序。 TreeSet的第二種排序方式。 當元素自身不具備比較性時,或者具備的比較性不是所需要的。 這時就需要讓集合自身具備比較性。 在集合初始化時,就有了比較方式。 需求: 往TreeSet集合中存儲自定義對象學生。 想按照學生的年齡進行排序。 記住,排序時,當主要條件相同時,一定判斷一下次要條件。 */ class TreeSetDemo { public static void main(String[] args) { TreeSet ts = new TreeSet(); ts.add(new Student("lisi02",22)); ts.add(new Student("lisi007",20)); ts.add(new Student("lisi09",19)); ts.add(new Student("lisi08",19)); //ts.add(new Student("lisi007",20)); //ts.add(new Student("lisi01",40)); Iterator it = ts.iterator(); while(it.hasNext()) { Student stu = (Student)it.next(); System.out.println(stu.getName()+"..."+stu.getAge()); } } } class Student implements Comparable//該接口強制讓學生具備比較性。 { private String name; private int age; Student(String name,int age) { this.name = name; this.age = age; } public int compareTo(Object obj) { //return 0; if(!(obj instanceof Student)) throw new RuntimeException("不是學生對象"); Student s = (Student)obj; System.out.println(this.name+"....compareto....."+s.name); if(this.age>s.age) return 1; if(this.age==s.age) { return this.name.compareTo(s.name); } return -1; } public String getName() { return name; } public int getAge() { return age; } }
import java.util.*; /* 當元素自身不具備比較性,或者具備的比較性不是所需要的。 這時需要讓容器自身具備比較性。 定義了比較器,將比較器對象作為參數傳遞給TreeSet集合的構造函數。 當兩種排序都存在時,以比較器為主。 定義一個類,實現Comparator接口,覆蓋compare方法。 */ class Student implements Comparable//該接口強制讓學生具備比較性。 { private String name; private int age; Student(String name,int age) { this.name = name; this.age = age; } public int compareTo(Object obj) { //return 0; if(!(obj instanceof Student)) throw new RuntimeException("不是學生對象"); Student s = (Student)obj; //System.out.println(this.name+"....compareto....."+s.name); if(this.age>s.age) return 1; if(this.age==s.age) { return this.name.compareTo(s.name); } return -1; } public String getName() { return name; } public int getAge() { return age; } } class TreeSetDemo2 { public static void main(String[] args) { TreeSet ts = new TreeSet(); ts.add(new Student("lisi02",22)); ts.add(new Student("lisi02",21)); ts.add(new Student("lisi007",20)); ts.add(new Student("lisi09",19)); ts.add(new Student("lisi06",18)); ts.add(new Student("lisi06",18)); ts.add(new Student("lisi007",29)); //ts.add(new Student("lisi007",20)); //ts.add(new Student("lisi01",40)); Iterator it = ts.iterator(); while(it.hasNext()) { Student stu = (Student)it.next(); System.out.println(stu.getName()+"..."+stu.getAge()); } } } class MyCompare implements Comparator { public int compare(Object o1,Object o2) { Student s1 = (Student)o1; Student s2 = (Student)o2; int num = s1.getName().compareTo(s2.getName()); if(num==0) { return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge())); /* if(s1.getAge()>s2.getAge()) return 1; if(s1.getAge()==s2.getAge()) return 0; return -1; */ } return num; } }
比較推薦的定制排序做法:
1、首先,定義一個Person類
public class Person { 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 Person(String name, int age) { super(); this.name = name; this.age = age; } public Person(){} }
(附加的練習:Student類)
public class Student implements Comparable{ 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(String name, int age) { super(); this.name = name; this.age = age; } @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; Student other = (Student) 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; } @Override public int compareTo(Object o) { int result; if(o instanceof Student){ Student stu = (Student)o; result = this.age-stu.age; if(result==0){ return this.getName().compareTo(stu.getName()); } }else{ throw new ClassCastException("不是一個學生對象!"); } return result; } public Student(){} @Override public String toString() { return "Student [name=" + name + ", age=" + age + "]"; } }
2、然后寫主程序類
import java.util.Comparator; import java.util.Iterator; import java.util.Set; import java.util.TreeSet; public class TestTreeSet { public static void main(String []args){ /* Set set = new TreeSet(); // set.add("123"); // set.add(123); // set.add(null); // set.add(new Student()); set.add(new Student("lisi07",22)); set.add(new Student("lisi02",16)); set.add(new Student("lisi008",22)); set.add(new Student("lisi10",19)); Iterator iterator = set.iterator(); while(iterator.hasNext()){ Student stu = (Student) iterator.next(); System.out.println(stu.getName()+"...."+stu.getAge()); } for(Object obj:set){ System.out.println(obj); }*/ Comparator comparator = new Comparator() { @Override public int compare(Object o1, Object o2) { int result; if(o1 instanceof Person&& o2 instanceof Person){ Person p1 = (Person) o1; Person p2 = (Person) o2; result = p1.getAge() - p2.getAge(); if(result == 0){ return p1.getName().compareTo(p2.getName()); } }else{ throw new ClassCastException("不能轉換為Person"); } return result; } }; Set set2 = new TreeSet(comparator); set2.add(new Person("lisi006",12)); set2.add(new Person("lisi002",6)); set2.add(new Person("lisi015",20)); set2.add(new Person("lisi013",20)); Iterator iterator = set2.iterator(); while(iterator.hasNext()){ Person p = (Person) iterator.next(); System.out.println(p.getName()+" "+p.getAge()+"\t"); } } }
