堆棧空間分配html
棧(stack)在計算機科學中是限定僅在表尾進行插入或刪除操做的線性表。棧是一種數據結構,它按照後進先出的原則存儲數據,先進入的數據被壓入棧底,最後的數據在棧頂,須要讀數據的時候從棧頂開始彈出數據。棧是隻能在某一端插入和刪除的特殊線性表。用桶堆積物品,先堆進來的壓在底下,隨後一件一件往上堆。取走時,只能從上面一件一件取。讀和取都在頂部進行,底部通常是不動的。棧就是一種相似桶堆積物品的數據結構,進行刪除和插入的一端稱棧頂,另外一端稱棧底。插入通常稱爲進棧,刪除則稱爲退棧。 棧也稱爲後進先出表。
java
Heap
程序員
堆(heap)又被爲優先隊列(priority queue)。儘管名爲優先隊列,但堆並非隊列。回憶一下,在隊列中,咱們能夠進行的限定操做是dequeue和enqueue。dequeue是按照進入隊列的前後順序來取出元素。而在堆中,咱們不是按照元素進入隊列的前後順序取出元素的,而是按照元素的優先級取出元素。算法
這就好像候機的時候,不管誰先到達候機廳,老是頭等艙的乘客先登機,而後是商務艙的乘客,最後是經濟艙的乘客。每一個乘客都有頭等艙、商務艙、經濟艙三種個鍵值(key)中的一個。頭等艙->商務艙->經濟艙依次享有從高到低的優先級。sql
java.lang.Object java.util.AbstractCollection<E> java.util.AbstractList<E> java.util.Vector<E> java.util.Stack<E>
public class Stack<E>
extends Vector<E>api
Stack
類表示後進先出(LIFO)的對象堆棧。它經過五個操做對類 Vector 進行了擴展 ,容許將向量視爲堆棧。它提供了一般的push 和 pop 操做,以及取堆棧頂點的 peek 方法、測試堆棧是否爲空的 empty 方法、在堆棧中查找項並肯定到堆棧頂距離的search 方法。數組
首次建立堆棧時,它不包含項。緩存
Deque
接口及其實現提供了 LIFO 堆棧操做的更完整和更一致的 set,應該優先使用此 set,而非此類。例如:安全
Deque<Integer> stack = new ArrayDeque<Integer>();
若是你的應用中涉及到的東西比較耗內存的話,好比:相機、第三方地圖、騰訊、新浪、錄音、視頻播放、大量圖片時,若是這些東西同時存在於應用中時,會有不少奇怪的問題出現,自動退出還不報錯等等一系列的問題,還有,若是咱們的應用中使用startActivity()過多並且並無及時finish()掉的話,也會出現這樣那樣的問題,好比:退出應用時沒有退出乾淨,或者莫名其妙的報OOM,啓動的服務自動掛起什麼的! 其實,Google已經提供了一套完整的機制讓開發人員控制活動棧與任務棧
像這樣的跳轉咱們在開發的過程當中算是很長見到的了,在這裏我就不貼代碼了 ,假如就是有三個活動窗口(Activity1,Activity2,Activity3,)按前後順序 從Activity1--startActivity()
到Activity2再到Activity3這個過程你們應該能夠想象的到,在這個過程生成的活動堆棧如圖所示:
數據結構
若是是點擊回退鍵的過程當中也會有不同一樣點擊了六次按鈕以後按的返回鍵,第一種效果必須點擊六次Back鍵後方可退出,而第二種效果只點擊一次便可退出,這就是Flag的魅力,激動….再來看Flag都有哪幾種吧,此處我列在這個地方,上面兩個效果中設置的是:i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);另外還有不少能夠控制活動堆棧與任務棧的Flag,小馬在這個地方隨便列出兩個,剩餘的Flag值以截圖的形式顯示,節約時間:
Task就像一個容器,而Activity就至關與填充這個容器的東西,第一個東西(Activity)則會處於最下面,最後添加的東西(Activity)則會在最低端。從Task中取出東西(Activity)則是從最頂端取出。
2、界面跳轉和服務的啓動都會用到Intent,如今介紹Intent Flag是關於Activity的跳轉
Intent intent = new Intent(this,xxx.class);
//若是activity在task存在,拿到最頂端,不會啓動新的Activity
intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
//若是activity在task存在,將Activity之上的全部Activity結束掉
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
//默認的跳轉類型,將Activity放到一個新的Task中
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//若是Activity已經運行到了Task,再次跳轉不會在運行這個Activity
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
若是加了 i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);操做下任務堆棧就能夠了,具體的緣由,也能夠用一句話來總結:若是在一個Activity中同一時間,要操做不用的功能,好比:跳轉時還要操做視頻錄音文件的播放什麼的,都得設置新的任務棧來啓動打開,若是不啓動新任務棧的話,有時候會無原無端的顯示空白還不報錯!上面的錯只是一個小點,小到能夠忽略不講,寫在這是提醒你們,該加的時候必須加Flag,至於何時加,你們能夠參照下官方的文檔及下面小馬貼出的官方文檔中解釋堆棧的圖解,加以理解學習,以下所示:Figure2:很少解釋,就是在A B 丙個任務堆棧,若是用戶正在於B任務堆棧進行交互時,A在等待喚醒,反之則反
Figure3: 下面這個就好玩了,學習了下官方的文檔,講的是:不管啓動了一個新的任務堆棧或者在同一堆棧中來啓動一個活動,按返回鍵也仍是會返回到用戶以前操做的Activity,若是以單例堆棧(相似單位模式)載入的話,就會在後臺生成一個針對於此活動的單獨的一個任務堆棧,當這個任務堆棧被喚醒到前臺時,此時的返回堆棧中就包含了從前幾個任務傳遞過來的棧頂的全部Activity,棧頂與棧底的顯示關係若是下圖:
這個地方順帶着講下,在控制活動堆棧時方式只有一種,就是直接在.java文件中setFlag,若是是控制任務堆棧的話能夠以addFlag或直接在全局配置文件中添加配置的方式來控制,你們能夠直接在AndroidManifest.xml文件中activity節點中添加哪下屬性:taskAffinity、launchMode、allowTaskReparenting、clearTaskOnLaunch、alwaysRetainTaskState、finishOnTaskLaunch,兩種控制任務堆棧的方式換湯不換藥,你們看我的習慣選擇使用就能夠了…切記,用的時候必定搞清楚你要加的標誌位是什麼意思,不要看到個task就addFlag,設置Flag是爲了讓應用更乾淨,控制更嚴密,若是加錯了標誌位,應用是不會報任何錯的,只是出現怪異的跳轉與關閉!!!
Stack是一個後進先出(last in first out,LIFO)的堆棧,在Vector類的基礎上擴展5個方法而來
Deque(雙端隊列)比起Stack具備更好的完整性和一致性,應該被優先使用
Stack自己經過擴展Vector而來,而Vector自己是一個可增加的對象數組( a growable array of objects)那麼這個數組的哪裏做爲Stack的棧頂,哪裏做爲Stack的棧底?
答案只能從源代碼中尋找,jdk1.6:
經過peek()方法註釋The object at the top of this stack (the last item of the Vector object,能夠發現數組(Vector)的最後一位即爲Stack的棧頂
pop、peek以及search方法自己進行了同步
push方法調用了父類的addElement方法
empty方法調用了父類的size方法
Vector類爲線程安全類
綜上,Stack類爲線程安全類(多個方法調用而產生的數據不一致問題屬於原子性問題的範疇)
結果:
Stack並不要求其中保存數據的惟一性,當Stack中有多個相同的item時,調用search方法,只返回與查找對象equal而且離棧頂最近的item與棧頂間距離(見源碼中search方法說明)