ArrayList它是List接口的真正的實現類。也是咱們開發中真正須要使用集合容器對象。數組
ArrayList類,它是List接口的實現。確定擁有角標。而且能夠存放重複元素,也可以使用List接口中的全部特有方法。ArrayList集合容器,它的底層使用的可變的數組做爲存儲元素的容器。安全
上述分析ArrayList底層的可變數組。這個可變數組也稱爲ArrayList集合的底層數據存儲的結構(數據結構)。 數據結構
ArrayList它的底層使用的可變數組:ide
它中增刪效率相對較低。查詢的效率較快。ArrayList它是JDK1.2出現的集合容器。它不保證數據的安全。學習
ArrayList中的方法所有來自於Collection和List接口。測試
List 接口的連接列表實現。實現全部可選的列表操做,而且容許全部元素(包括 null)。this
除了實現 List 接口外,LinkedList 類還爲在列表的開頭及結尾 get、remove 和 insert 元素提供了統一的命名方法。這些操做容許將連接列表用做堆棧、隊列或雙端隊列。編碼
LinkedList集合它是List接口的直接實現類。它實現了Collection和List接口中的全部方法。 spa
LiknedList集合它的底層使用的連接列表:設計
LinkedList:集合底層使用的鏈表結構,因爲鏈表有頭和尾,所以在LinkedList集合中從新定義了新的方法,這些方法都是圍繞鏈表的頭和尾而設計的方法:
addFirst
addLast
removeFirst
removeLast
getFirst
getLast
鏈表結構能夠完成數據結構中的部分結構的實現:
隊列:先進先出,後進後出。最早 進入到結構中的數據,被最早取出。例如:排隊買票,火車過山洞。
堆棧:先進後出,後進先出。例如:Java內存結構中的棧內存。手槍彈夾。
1 //模擬隊列或者堆棧數據結構 2 class Queue{ 3 4 //定義一個LinkedList集合 5 private LinkedList list = new LinkedList(); 6 7 public void myAdd( Object obj ){ 8 list.addFirst(obj); 9 } 10 11 public Object myGet(){ 12 return list.removeLast(); 13 } 14 15 public boolean isEmpty(){ 16 return list.isEmpty(); 17 } 18 19 } 20 //測試類 21 public class LinkedListDemo2 { 22 public static void main(String[] args) { 23 24 Queue q = new Queue(); 25 26 q.myAdd("aaa"); 27 q.myAdd("bbb"); 28 q.myAdd("ccc"); 29 q.myAdd("ddd"); 30 31 while( !q.isEmpty() ){ 32 System.out.println(q.myGet()); 33 } 34 } 35 }
List:它下面的集合容器都有腳標,均可以使用角標或者ListIterator進行遍歷。
ArrayList:它的底層是可變數組,增刪慢,查詢快。不安全。
LinkedList:它的底層是鏈表結構,有頭和尾,能夠模擬隊列或者堆棧數據結構。增刪快,查詢慢。不安全
Vector集合是它JDK1.0時期就存在的一個集合容器對象。在JDK1.2的時候出現了集合體系,Vector變成List接口下的一個實現類。
Vector的底層使用的也是可變數組,和ArrayList底層一致。Vector它能夠保證安全,由於它的什麼效率都慢。
後期開發中看到Vector就能夠直接把它當作ArrayList使用便可。
Vector中的方法名只要是和element相關的都是Vector的原生方法。其餘的都是從Collection或者List接口中實現的。
1 /* 2 * 介紹古老的Vector集合 3 */ 4 public class VectorDemo { 5 public static void main(String[] args) { 6 7 //建立集合對象 8 Vector v = new Vector(); 9 10 v.addElement("aaa"); 11 v.addElement("aaa"); 12 v.addElement("abc"); 13 v.addElement("ccc"); 14 15 //遍歷 16 for( Enumeration en = v.elements(); en.hasMoreElements() ; ){ 17 System.out.println(en.nextElement()); 18 } 19 20 for( Iterator it = v.iterator(); it.hasNext() ; ){ 21 System.out.println(it.next()); 22 } 23 } 24 }
Enumeration:它是Iterator的前身,也能夠遍歷集合容器。
可是因爲它的功能和Iterator嚴重重複,而且Iterator中提供的方法名稱比Enumeration中的方法名短。
開發中咱們優先使用Iterator,而不使用Enumeration迭代集合。
Set接口是Collection接口下的一個子接口。它和List接口相同,都是Collection的子接口。
區別:
List:有腳本、能夠重複、擁有特有的ListIterator迭代器
Set:沒有腳本、不能包含重複元素,沒有特有的迭代器,只能使用Iterator進行遍歷。
Set接口沒有本身的特有的方法,全部方法所有來自於Collection接口。
重點學習Set接口下的兩個實現類:
HashSet:
TreeSet:
此類實現 Set 接口,由哈希表(其實是一個 HashMap 實例)支持。它不保證 set 的迭代順序;特別是它不保證該順序恆久不變。此類容許使用 null 元素。
HashSet集合的底層使用的哈希表結構。
若是多個對象它們計算出的哈希值相同,這時在計算機中稱爲哈希衝突。若是哈希值相同了,這時必須調用對象的equals方法比較2個對象(多個對象)是不是同一個對象。
任何給哈希表中存儲的對象都應該具有hashCode和equals方法。
1 /* 2 * 演示HashSet集合 3 */ 4 public class HashSetDemo { 5 public static void main(String[] args) { 6 7 //建立集合對象 8 HashSet set = new HashSet(); 9 10 //添加元素 11 set.add("bbb"); 12 set.add("cccc"); 13 set.add("cccc"); 14 set.add("abc"); 15 set.add("abc"); 16 //遍歷HashSet集合 17 for( Iterator it = set.iterator() ; it.hasNext(); ){ 18 System.out.println(it.next()); 19 } 20 } 21 }
1 /* 2 * 演示給HashSet中保存自定義類的對象 3 */ 4 public class HashSetDemo2 { 5 public static void main(String[] args) { 6 7 //建立集合對象 8 HashSet set = new HashSet(); 9 10 //建立自定義對象 11 //Person p = new Person("華安",23); 12 //set.add(p); 13 set.add(new Person("華安",23)); 14 set.add(new Person("華安",23)); 15 set.add(new Person("秋香",18)); 16 set.add(new Person("9527",23)); 17 set.add(new Person("小書童",33)); 18 19 //遍歷 20 for( Iterator it = set.iterator() ; it.hasNext(); ){ 21 System.out.println( it.next() ); 22 } 23 } 24 }
分析:
咱們本身定義了一個Person類,而後建立Person對象,將這些Person對象存儲到HashSet集合中。
但願同姓名和年齡的Person對象,應該是同一我的,在集合中只能有一個。可是經過程序發現依然能夠保存多個同姓名和年齡的Person對象。
HashSet集合底層使用的哈希表,給哈希表中存儲對象的時候,須要調用當前對象本身的hashCode計算位置,equals判斷對象是否相同。而咱們的Person類繼承了Object類,天然就會具有hashCode和equals方法。
可是Person類中並無去複寫hashCode和equals方法,說明在將Person對象給HashSet集合中保存的時候,調用的hashCode和equals方法依然使用的Object類中的方法。
Object類中的equals方法是在比較2個對象的地址值是否相同。
hashCode方法計算哈希值的是也是根據對象的地址值在進行計算。
若是建立了多個Person對象,它們的姓名和年齡相同,咱們認爲應該是同一我的,可是因爲是new了屢次,在堆中就會有多個Person對象,它們的地址值確定是不相同的。
HashSet保證對象的惟一依賴當前給HashSet集合中保存的對象的hashCode和equals方法。
使用hashCode計算位置,使用equals比較2個對象是否相同。
要保證給HashSet集合中存儲的自定義對象中的數據惟一,自定義對象所屬的類須要複寫Object類中的hashCode和equals方法 。
HashSet集合不保證存取的順序,保證對象惟一。
LinkedHashSet它是HashSet集合的子類,它也屬於Set接口下的集合容器,一樣也能保證對象的惟一。
和HashSet的區別是:LinkedHashSet能夠保證存放的元素的存取順序一致。
LinkedHashSet它沒有本身的特有方法,全部方法所有來自於父類。
1 /* 2 * 演示LinkedHashSet集合 3 */ 4 public class LinkedHashSetDemo { 5 public static void main(String[] args) { 6 7 //建立集合對象 8 LinkedHashSet set = new LinkedHashSet(); 9 10 set.add("ccc"); 11 set.add("aaa"); 12 set.add("abc"); 13 set.add("ccc"); 14 set.add("aaa"); 15 16 //遍歷 17 for (Iterator it = set.iterator(); it.hasNext();) { 18 System.out.println(it.next()); 19 } 20 } 21 }
基於 TreeMap
的 NavigableSet
實現。使用元素的天然順序對元素進行排序,或者根據建立 set 時提供的 Comparator
進行排序,具體取決於使用的構造方法。
TreeSet集合它是Set接口的間接實現類。TreeSet集合它也不能存放重複的元素。
TreeSet集合的底層使用的數據結構中的二叉樹(紅黑樹)結構。這種數據結構能夠對保存在其中的數據進行排序。
1 /* 2 * TreeSet集合的簡單演示 3 */ 4 public class TreeSetDemo { 5 public static void main(String[] args) { 6 7 //建立集合對象 8 TreeSet set = new TreeSet(); 9 10 //添加元素 11 set.add("ddd"); 12 set.add("aaa"); 13 set.add("bbb"); 14 set.add("bbb"); 15 set.add("abc"); 16 set.add("ABC"); 17 set.add("ABC"); 18 set.add("aBC"); 19 set.add("eee"); 20 set.add("def"); 21 set.add("def"); 22 set.add("ddf"); 23 set.add("ddf"); 24 25 //遍歷 26 for( Iterator it = set.iterator() ; it.hasNext(); ){ 27 System.out.println(it.next()); 28 } 29 } 30 }
介紹數據結構中的樹結構:
樹結構:
二叉樹:每一個節點最多隻能有2個子節點。
非規則二叉樹:有點節點可能會有2個子節點,有的只有一個。甚至沒有。
普通的樹結構:非規則樹結構。
二叉樹:
若是將自定義對象存儲到TreeSet集合(二叉樹結構)中,這時底層會將傳遞的這個對象強制轉成Comparable類型。
發生上述的緣由是:
給TreeSet中保存的對象須要進行比較大小,而後肯定它們在二叉樹中存儲位置,存儲的對象就必須具有比較大小的功能。若是要使一個對象具有比較大小的功能,這個對象所屬的類須要實現Java中提供的Comparable接口。實現其中的compareTo方法。
1 /* 2 * 演示給TreeSet集合中保存自定義對象 3 */ 4 public class TreeSetDemo2 { 5 6 public static void main(String[] args) { 7 8 //建立TreeSet集合對象 9 TreeSet set = new TreeSet(); 10 11 set.add(new Person("華安",23)); 12 set.add(new Person("華安",23)); 13 set.add(new Person("秋香",13)); 14 set.add(new Person("秋香",23)); 15 set.add(new Person("石榴",33)); 16 17 //遍歷 18 for( Iterator it = set.iterator() ; it.hasNext() ; ){ 19 System.out.println(it.next()); 20 } 21 } 22 }
將對象保存到TreeSet集合中過程當中:
在將對象保存到集合中的時候,須要將當前這個對象和集合中已經存在的對象進行大小比較,也就是去調用對象的compareTo方法。若是這個方法返回的結果是零,就說明當前正要往集合中存儲的對象和已經在集合中的對象大小同樣。這時這個對象就不會被保存到集合中。
1 /* 2 * 讓咱們本身的類實現Comparable接口,讓其對象具有比較大小的功能 3 */ 4 5 public class Person implements Comparable{ 6 private String name; 7 private int age; 8 9 public Person(String name, int age) { 10 this.name = name; 11 this.age = age; 12 } 13 public String getName() { 14 return name; 15 } 16 public void setName(String name) { 17 this.name = name; 18 } 19 public int getAge() { 20 return age; 21 } 22 public void setAge(int age) { 23 this.age = age; 24 } 25 @Override 26 public String toString() { 27 return "Person [name=" + name + ", age=" + age + "]"; 28 } 29 /* 30 * 實現Comparable接口中的compareTo方法 31 * 須要在compareTo方法中根據對象的屬性數據進行大小的比較 32 * 33 * compareTo方法的調用時間: 34 * 當正要給TreeSet中保存對象的時候,由TreeSet集合的底層,會將 35 * 當前這個對象強轉成Comparable類型,而後再用強轉後的這個對象 36 * 調用compareTo方法,將已經在集合中的對象傳遞Object o ,而後 37 * 在compareTo方法中比較當前正要存放的對象和已經在集合中的對象的大小。 38 */ 39 public int compareTo(Object o) { 40 41 //判斷傳遞進來的o是不是Person類型 42 if( !(o instanceof Person) ){ 43 //判斷成立,說明當前傳遞進來的o不是Person類型 44 throw new ClassCastException("傳遞的對象不是Person類型"); 45 } 46 Person p = (Person) o; 47 /* 48 //比較 49 if( this.age == p.age ){ 50 //年齡相同,判斷姓名 51 if( this.name.equals(p.name) ){ 52 //判斷成立說明 年齡和姓名都相同認爲是同一我的 53 return 0; 54 }else{ 55 return this.name.compareTo(p.name); 56 } 57 }else{ 58 return this.age - p.age; 59 } 60 */ 61 int temp = this.age - p.age; 62 return temp == 0 ? this.name.compareTo(p.name) : temp; 63 } 64 }
需求:將字符串數據保到TreeSet集合中,要求按照字符串的長度進行排序。
「AAAAA」 「aaa」
分析:
自己TreeSet集合能夠對存放在其中的任何對象進行排序,依賴的是對象本身的compareTo方法。String類自己已經具有compareTo方法,可是這個方法是按照字符串中每一個字符的編碼值大小進行比較。而需求要求按照字符串的長度進行比較。String類中的compareTo方法不能知足需求。
針對上述的問題,自己應該能夠定義一個新的類,繼承String類,複寫compareTo方法,而後使用子類本身的比較方式。可是因爲String類被final修飾,不能再有子類。
Java給出另一種處理方案:若是對象自身具有了比較功能,或者對象自身根本就沒有比較功能,這時依然須要對這些對象進行排序,咱們能夠本身建立一個專門負責比較對象大小的新的比較器對象。
1 /* 2 * 演示使用比較器對TreeSet集合中的元素(對象)進行比較大小排序 3 */ 4 public class TreeSetDemo3 { 5 public static void main(String[] args) { 6 //沒有傳遞比較器,會按照元素自身的compareTo進行大小比較 7 //TreeSet set = new TreeSet( ); 8 //傳遞比較器 9 TreeSet set = new TreeSet( new MyComparator()); 10 11 set.add("AAAAA"); 12 set.add("aaa"); 13 set.add("aa"); 14 set.add("AAA"); 15 set.add("AAAAA"); 16 17 for (Iterator it = set.iterator(); it.hasNext();) { 18 System.out.println(it.next()); 19 } 20 } 21 } 22 23 //自定義比較器(本身定義比較規則) 24 public class MyComparator implements Comparator{ 25 26 //實現按照字符串長度比較大小 27 public int compare(Object o1, Object o2) { 28 29 //按照長度比較 30 if( !( o1 instanceof String && o2 instanceof String ) ){ 31 throw new ClassCastException("數據類型不統一,沒法比較"); 32 } 33 34 String s1 = (String) o1; 35 String s2 = (String) o2; 36 37 int temp = s1.length() - s2.length(); 38 39 return temp == 0 ? s1.compareTo(s2) : temp ; 40 } 41 }
相同點:Comparator和Comparable:它們均可以提供比較大小的方法。
不一樣點:
Comparable:它是讓某個類具有比較功能,當建立出這個類的對象,就能夠直接使用這個對象中的compareTo方法進行比較大小。Comparable是讓對象本身具有了比較功能
Comparator:它是提供比較兩個對象大小,可是這個功能和對象自身並無任何的關係。只要將須要比較的兩個對象傳遞給compare方法便可。提供單獨的比較器對象,能夠比較任意的兩個對象