摘要:迭代器解決了這個問題。刪除后于是我們可以寫一個方法,接受一個類型,然后讓他調用方法,這就不需要考慮這個是個還是了,也就是說,可以將遍歷容器的操作與序列底層的結構分離,迭代器統一了對容器類的訪問方式。十二和兩種遍歷的方法,與迭代器方法。
一、泛型和類型安全的容器
package tij.hoding; import java.util.ArrayList; public class Test { @SuppressWarnings("unchecked") public static void main(String[] args) { ArrayList apples=new ArrayList(); for(int i=0;i<2;i++){ apples.add(new Apple()); } apples.add(new Orange()); for(int i=0;i在運行期的類型轉換時會出現問題,因為使用get方法的時候取出來的其實object類型,之前程序中放進去了一個orange卻要將他轉成一個apple。
因此需要使用類型參數來指定這個容器實例可以保存的類型,通過使用類型參數,就可以在編譯期放置將錯誤的類型放在容器中,上面的代碼改成下面類型package tij.hoding; import java.util.ArrayList; public class Test { public static void main(String[] args) { ArrayListapples=new ArrayList<>(); for(int i=0;i<2;i++){ apples.add(new Apple()); } for(int i=0;i 同樣,可以將容器的類型參數的指定類型以及其子類類型的實例變量放進這個容器中,例子略
二、基本概念Java容器類可以劃分為兩個不同的概念
Collection
一個存儲獨立元素的序列,不同序列有不同的規則:List必須按照插入順序保存元素;Set不能有重復元素;Queue按照排隊規則確定對象產生的順序。Map
一組成對的簡直對對象然而大多數情況在編寫代碼的時候都是與接口打交道,唯一需要精確指定使用的容器類型的地方就是創建的時候,如下
Listapples=new ArrayList (); 就是說多數情況我們是面向接口編程的,但也并不都是這樣,比如如果我們要使用LinkedList里的特有的功能,就不能用這種方法了。
三、添加一組元素Collections和Arrays類中提供了很多與序列相關的方法,有啥自己去找API看去就行了。
注明package tij.hoding; import java.util.Arrays; import java.util.List; public class Test { public static void main(String[] args) { Listsnow1=Arrays.asList(new Crusty(),new Slush(),new Powder(),new Light()); List snow2=Arrays.asList(new Light(),new Heavy()); } } class Snow{} class Powder extends Snow{} class Light extends Powder{} class Heavy extends Powder{} class Crusty extends Snow{} class Slush extends Snow{} 書上說snow2是創建不了的,我用的是JDK1.8發現是可以創建的。
四、容器的打印沒啥說的,數組的打印可以用Arrays.toString方法
五、ListList接口在Collection基礎上添加了大量方法
基本的ArrayList,訪問快,中間插入和移除較慢
LinkedList,進行中間的插入刪除代價低
六、迭代器
方法找API看對于List,add方法是插入元素的方法,get方法是去除元素的方法,但是這是有弊端的,如果使用容器,如果需要對元素進行操作,就必須要針對容器的確切類型進行編程,舉個例子,如果要從一個List里取出元素,我們寫了一些方法,但如果希望將這些方法再運用到同是Collection類的set類上,就不行了,因為set根本沒有get方法。迭代器解決了這個問題。
package tij.hoding; import java.util.ArrayList; import java.util.Iterator; public class Test { public static void main(String[] args) { ArrayListstr_list = new ArrayList (); for (int i = 0; i < 10; i++) str_list.add("123134"); Iterator it = str_list.iterator(); while (it.hasNext()) { System.out.println(it.next()); } it = str_list.iterator(); for (int i = 0; i < 5; i++) { it.next(); it.remove(); } System.out.println("----刪除后"); it = str_list.iterator(); while (it.hasNext()) { System.out.println(it.next()); } } } 于是我們可以寫一個方法,接受一個collection類型,然后讓他調用iterator()方法,這就不需要考慮這個collection是個list還是set了,也就是說,可以將遍歷容器的操作與序列底層的結構分離,迭代器統一了對容器類的訪問方式。
1.ListIterator這是個List專用的迭代器,他可以雙向移動,可以生成索引,可以使用set方法對元素進行替換,而且在創建的時候還可以指從哪開始迭代,具體看API
七、LinkedListLinkedList里有很多功能類似的方法,比如peek、element、getFirst,這是因為常以linkedList為基礎制作堆棧等數據結構,在這種數據結構中使用push啊pop啊更合適,雖然我覺得有一些= =額= =恩。。。。
八、Stack沒啥好說的,就是用Linkedlist實現,LIFO
九、SetSet保證集合內元素的唯一性,同時Set也有不同的類型:HashSet使用了散列函數;TreeSet將元素存儲在紅黑樹數據結構中,可以完成元素按比較方法的排序;LinkedHashSet也使用了散列,但它通過使用鏈表維護了元素插入順序
十、Map存儲映射關系的數據結構
十一、QueueFIFO的容器
1.PriorityQueue
看API挺簡單的優先級隊列聲明下一個彈出的元素是最需要的元素(優先級最高)。當用PriorityQueue上調用offer方法插入一個對象時,這個對象會在隊列中被排序,可以使用對象的自然排序也可以提供自己的Comparator來修改排序規則。PriorityQueue可以確保調用各種方法時,根據優先級進行操作。
package tij.hoding; import java.util.Arrays; import java.util.List; import java.util.PriorityQueue; import java.util.Queue; import java.util.Random; public class Test { public static void main(String[] args) { PriorityQueue十二、Collection和IteratorpriorityQueue = new PriorityQueue (); Random rand = new Random(47); for (int i = 0; i < 10; i++) { priorityQueue.offer(rand.nextInt(i + 10)); } printQ(priorityQueue); List ints = Arrays.asList(25, 22, 20, 18, 14, 9, 3, 1, 1, 2, 3, 9, 14, 18, 21, 23, 25); priorityQueue = new PriorityQueue (ints); printQ(priorityQueue); } @SuppressWarnings("rawtypes") static void printQ(Queue queue) { while (queue.peek() != null) { System.out.print(queue.remove() + " "); } System.out.println(); } } 兩種遍歷的方法,foreach與迭代器方法。
十三、Foreach與迭代器
同時有一種默認的AbstractCollection,繼承他可以較為簡單的將自己的類變成Collection類型而不用實現原Collection全部的方法因為有了迭代器,所以有了Foreach功能,這個功能真的很強大
package tij.hoding; import java.util.Collection; import java.util.Collections; import java.util.LinkedList; public class Test { public static void main(String[] args) { Collectioncs = new LinkedList (); Collections.addAll(cs, "Take the long way home".split(" ")); for (String s : cs) { System.out.print(s + " "); } } } 而這是因為Java se5引入了Iterable幾口,實現了Iterable接口的類都可應用于Foreach之中。比如下面
package tij.hoding; import java.util.Iterator; public class Test { public static void main(String[] args) { for (String s : new IterableClass()) { System.out.print(s + " "); } } } class IterableClass implements Iterable{ protected String[] words = "And that is how we know the Earth to be banana-shaped" .split(" "); @Override public Iterator iterator() { return new Iterator () { private int index = 0; @Override public boolean hasNext() { return index < words.length; } @Override public String next() { return words[index++]; } }; } } 首先要搞懂Foreach語句中for(element:container)里的container要是iterable類型的才可以,foreach在遍歷時,首先調用container的iterator方法得到這個iterator,然后就是在調用這個iterator的的hasNext和next方法
1.適配器方法慣用法假如現在有一個類記錄了一串兒單詞,希望能運用Foreach方法將他遍歷,只要讓他實現Iterable接口實現Iterator功能就可以了,但是現在希望他既能順向遍歷,又能逆向遍歷,這就不好辦了,因為你只能重寫Iterator一次啊。
一種解決方案就是所謂的適配機器方法,當你有一個接口并需要另一個接口的時候,編寫適配器就可以解決問題。package tij.hoding; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; public class Test { public static void main(String[] args) { ReversibleArrayListral = new ReversibleArrayList ( Arrays.asList("To be or not to be".split(" "))); for (String s : ral) { System.out.print(s + " "); } System.out.println(); for (String s : ral.reversed()) { System.out.print(s + " "); } } } @SuppressWarnings("serial") class ReversibleArrayList extends ArrayList { public ReversibleArrayList(Collection c) { super(c); } public Iterable reversed() { return new Iterable () { @Override public Iterator iterator() { return reversed_iterator(); } private Iterator reversed_iterator() { return new Iterator () { int current = size() - 1; public boolean hasNext() { return current > -1; } public T next() { return get(current--); } }; } }; } } 其實這個程序我看了半天才看懂,首先要搞懂Foreach語句中for(element:container)里的container要是iterable類型的才可以,foreach在遍歷時,首先調用container的iterator方法得到這個iterator,然后就是在調用這個iterator的的hasNext和next方法。然后再順序遍歷的時候,傳入的是ral,然后調用ral自身的iterator本身的hasNext和next方法,就是順序遍歷了;在逆向遍歷的時候,傳入的是一個新的iterable,得到的也是一個新的iterator,然后調用的就是這個新的iteratoriterator的兩個方法。
另外我想了一下next方法里的get方法是誰的,然后用了內部類訪問外部的方法也能調用ReversibleArrayList.this.get()于是我們就可以弄很多很多不同的遍歷規則了,比如隨機遍歷啊
package tij.hoding; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Random; public class Test { public static void main(String[] args) { ReversibleArrayListral = new ReversibleArrayList ( Arrays.asList("To be or not to be".split(" "))); for (String s : ral) { System.out.print(s + " "); } System.out.println(); for (String s : ral.reversed()) { System.out.print(s + " "); } System.out.println(); for (String s : ral.randomized()) { System.out.print(s + " "); } } } @SuppressWarnings("serial") class ReversibleArrayList extends ArrayList { public ReversibleArrayList(Collection c) { super(c); } public Iterable reversed() { return new Iterable () { @Override public Iterator iterator() { return reversed_iterator(); } private Iterator reversed_iterator() { return new Iterator () { int current = size() - 1; public boolean hasNext() { return current > -1; } public T next() { return ReversibleArrayList.this.get(current--); } }; } }; } public Iterable randomized(){ return new Iterable (){ @Override public Iterator iterator() { List shuffle= ReversibleArrayList.this; Collections.shuffle(shuffle,new Random(47)); return shuffle.iterator(); } }; } } 可以注意到在隨機遍歷的時候,實際返回了一個新的序列的iterator這是為了不打亂原始的序列的順序
附一張簡單的容器分類
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/67583.html
摘要:內部類中也可以取得這個外部類對象引用。創建成員內部類對象的時候需要外部類對象。另外在方法中的內部類不能加等權限修飾符,只能加和修飾符。可以在接口內部定義內部類,而且他們即使沒有修飾,也會自動變成的。 Thinking in Java撈干貨,寫筆記 一、成員內部類 1.最基本使用 public class Demo { class Contents{ privat...
摘要:四上的操作看五格式化輸出運用和語言很相似和是等價的喲類格式化說明符轉換六正則表達式網上教程學七掃描輸入新增了類。 一、不可變String String類型的對象是不可變的,所有的改變實際上都是創建了一個新的String對象,另外當String作為傳入參數的時候,其實實際上傳入的是這個引用的一個拷貝,這個方法結束了之后這個傳入的引用也就消失了,原來的那個String不會受到方法內的影響而...
摘要:基類導出類導出類繼承了基類的特點,基類和導出類具有相同的基礎接口,形成兩者差異的做法在導出類中添加新方法在導出類型中添加新的接口元素,擴展了接口。覆蓋在導出類用創建方法的新定義,覆蓋基類中的方法定義純粹替代,只覆蓋。 一、抽象過程 建模基于計算機的結構 解空間的解 匯編語言:對底層機器的輕微抽象 命令式語言:匯編語言的抽象 建模基于待解決問題 問題空間的元素 面向對象 二、每個...
摘要:通過運行時類型信息,程序能夠使用基類的指針或引用來檢查這些指針或引用所指的對象的實際派生類型。編程應該盡量面向接口編程,應該對類型信息盡量的少了解二對象看書,書上寫得好靜態語句塊在這個類被加載的時候運行。 一、為什么需要RTTI Run-Time Type Information。通過運行時類型信息,程序能夠使用基類的指針或引用來檢查這些指針或引用所指的對象的實際派生類型。編程應該盡量...
摘要:而這可以通過注解辦到,在代碼中以指令語言的形式化方法來為代碼提供更多信息。有注解的說明這個成員變量是一個列名,然后根據注解信息來生成相應的語句。也就是說把注解信息提取了出來。 注解是向代碼中添加信息的一種方法,并且在之后還可以使用這些數據就比如這個方法是用來剝香蕉的,但是我們看就是一串代碼,我們沒辦法在代碼里寫一段指令說我這個程序是用來剝香蕉的,當然除了注釋。而這可以通過注解辦到,在代...
閱讀 1048·2021-11-22 15:33
閱讀 3357·2021-11-08 13:20
閱讀 1368·2021-09-22 10:55
閱讀 2053·2019-08-29 11:08
閱讀 771·2019-08-26 12:24
閱讀 3068·2019-08-23 17:15
閱讀 2225·2019-08-23 16:12
閱讀 1933·2019-08-23 16:09