List繼承自Collection接口,是有序可重複的集合。java
它的實現類有:ArrayList、LinkedList、Vector、Stack算法
本質上是一個能存儲任意類型的對象的動態數組,元素的刪除和添加涉及到數組的擴容以及拷貝元素,因此效率很慢。因爲數組是能夠經過下標來查找的,所以查找速度快。數組
基於雙向鏈表實現,增刪快,查找慢。根據鏈表的性質,增長元素時只需讓前一個元素記住本身就行,刪除的時候讓前一個元素記住後一個元素,後一個元素記住前一個元素,這種增刪的效率比較高,但查找元素須要遍歷鏈表,效率低。安全
public static void main(String[] args){ List<Dog> list = new LinkedList<>(); System.out.println(list.size()); Dog dog1 = new Dog("小蘇","藏獒"); Dog dog2 = new Dog("小王","二哈"); Dog dog3 = new Dog("小李","金毛"); ((LinkedList<Dog>) list).addFirst(dog1); list.add(dog2); ((LinkedList<Dog>) list).addLast(dog3); System.out.println(list); System.out.println(((LinkedList<Dog>) list).getFirst()); System.out.println(list.get(1)); System.out.println(((LinkedList<Dog>) list).getLast()); }
基於數組實現,線程同步的遺留集合類,和ArrayList原理相同,可是線程安全,效率低。ide
後進先出this
Set繼承自Collection接口,是無序不可重複的集合線程
它的實現類有HashSet、LinkedHashSet、TreeSetcode
基於哈希表實現,元素存儲的地址是該元素的哈希值。對象
HashSet存儲元素的步驟:blog
public static void main(String[] args) { Set<String> set = new HashSet<>(); set.add("邵陽---長沙"); set.add("武漢---南京"); set.add("合肥---北京"); set.add("武漢---南京"); System.out.println("-------第一種輸出方式:toString方法--------"); System.out.println(set); System.out.println("-------第二種輸出方式:加強for循環--------"); for (String str: set) { System.out.println(str); } System.out.println("-------第三種輸出方式:迭代器方法--------"); Iterator<String> iterator = set.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); } // set集合是無序的,所以沒有下標,沒法用for循環來遍歷 }
@Test public void setObject(){ Set<Student> set = new HashSet<>(); set.add(new Student("小貝 ",9)); set.add(new Student("小胡 ",19)); set.add(new Student("小貝 ",9)); set.add(new Student("小福 ",23)); Iterator<Student> iterator = set.iterator(); while (iterator.hasNext()){ /* * 因爲hash表示無序的,所以輸出結果可能和存儲結果不一致 */ System.out.println(iterator.next().toString()); } /* * 若Student類重寫了equals方法,則第二個小貝不會被存入set, * 這種狀況下只會比較兩個小貝的名字和年齡的值,由於兩個小貝的名字和年齡同樣,所以他們被認爲是兩個相同的對象 * 若Student類沒有重寫equals方法,則第二個小貝會被存入set, * 這種狀況下只會比較兩個小貝的地址,由於是兩個不一樣的對象因此地址不一樣,所以他們被認爲是兩個不一樣的對象 */ }
/* * 被重寫的equals方法 */ @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Student student = (Student) o; return age == student.age && Objects.equals(name, student.name); /* * 注意基本類型的變量直接用==比較,而對象類型的,分狀況討論: * 若只比較值,則用equals方法,由於String類重寫了equals方法 */ }
基於哈希表和雙向鏈表實現,元素有序且不可重複,存儲步驟和HashSet一致,元素的順序是其存儲順序
@Test public void printLinkedHashList() { Set<String> set = new LinkedHashSet<>(); set.add("絕地求生"); set.add("球球大做戰"); set.add("守望先鋒"); set.add("超級瑪麗"); set.add("超級瑪麗"); Iterator<String> iterator = set.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); } /* 輸出結果和存儲結果一致: * 絕地求生 * 球球大做戰 * 守望先鋒 * 超級瑪麗 */ }
TreeSet是基於紅黑樹的有序且不可重複的集合,元素的順序和元素自己有關,和存儲順序無關
/* * 這個方法在執行的時候會報錯,由於在TreeSet在存儲時不知道根據學生的姓名仍是年齡來排序,準確地說,Student * 類沒有實現Comparable接口,所以沒法對Student排序。將一組亂序的數字或字符串存入TreeSet,從新輸出會獲得* 一組有序的數據,由於String類默認實現了Comparable接口。 * 報錯信息以下:java.lang.ClassCastException: Student cannot be cast to java.lang.Comparable */ @Test public void testSort() { Set<Student> set = new TreeSet<>(); set.add(new Student("小貝 ",9)); set.add(new Student("小胡 ",19)); set.add(new Student("小貝 ",10)); set.add(new Student("小福 ",23)); Iterator<Student> iterator = set.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); } }
/* * 對Student類進行修改,讓他繼承Comparable接口,並重寫Comparable裏的comparaTo方法,按照學生的年齡進行* 排序 */ public class Student implements Comparable<Student>{ private String name; private int age; public Student(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } @Override public void comparaTo() { } @Override public int comparaTo(Student o) { /* * 結果爲負,排在o對象以前 * 結果爲正,排在o對象以後 * 結果爲0, 說明兩個對象相等 */ return this.age - o.age; } }