Java知识整理——容器
生活随笔
收集整理的這篇文章主要介紹了
Java知识整理——容器
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Java Collections 框架 提供了一系列支持對象集合操作的設計良好的接口和類. Java Collections框架中最基礎的接口是:
Collection, 表示一組對象(元素).
Set, 包含非重復元素的集合.
List, 包含非重復元素的有序集合.
Map, 包含非重復鍵的鍵值對的對象.
Collection接口描述的是由元素組成的對象組. Collection的每一個具體實現可以選擇自己的方式來管理元素. 一些集合允許存在重復鍵, 另一些則不允許.
當處理實際實現時復制和序列化的語義和效果才會起作用. 因此, 集合類的具體實現應該決定它們將怎樣被復制和序列化.
Iterator接口提供了許多能夠疊代集合的方法.每個java集合(Collection)都含有一個返回Iterator實例的iterator方法. 疊代器在疊代過程中能夠移除底層集合中的元素.
它們之間的不同如下:
Iterator能夠遍歷Set和List集合, 而ListIterator只能用來遍歷List.
Iterator只能正向遍歷集合, 而ListIterator可以雙向遍歷List.
ListIterator實現了Iterator接口并提供了額外的功能, 例如添加元素, 替換元素, 取得上一個或上一個元素索引, 等等.
Iterator的fail_safe特性是對底層集合的拷貝進行操作, 因此對集合的任何改變都不會有影響. java.util包下的所有集合類是fail-fast的, 但java.util.concurrent包下的集合類是fail-safe的. fail-fast疊代器會拋出ConcurrentModificationException, 而fail-safe疊代器不會拋出這種異常.
Java 中的 HashMap 是用來存儲鍵值對的。 HashMap 需要一個 hash 函數,它使用 hashCode 和 equals 方法,來進行 collection 中元素的保存和查找。調用 put 方法時,HashMap 會計算鍵(key)的 hash 值,然后將鍵值對存到 collection 的適當索引下。如果鍵已經存在,那么相應的值會更新。HashMap 的重要特征主要有它的容量,裝載因子(load factor)和容量擴充(threshold resizing)。
Java中的 HashMap 使用 hashCode 和 equals 方法來確定鍵值對的索引。根據鍵去查詢對應的值時,同樣會用到這兩個方法。如果這兩個方法沒有正確實現,兩個不同的鍵可能會產生相同的 hash 值,因此會被 collection 認為是相同的。并且,這兩個方法在檢測重復時也會用到。因此,這兩個方法都要正確實現,對 HashMap 的正確性和效率都至關重要。
HashMap、HashTable這兩個類都實現了Map接口,因此有些非常相似的特征,但他們在以下特性中又有所不同:
HashMap的key與value都允許null值的存在,而HashTable則既不允許key為null,也不允許value為null。
HashTable是線程同步的,而HashMap則不是。因此,在單線程環境下HashMap是首選,而HashTable更適合在多線程環境下使用。
HashMap提供了它鍵的set集合,因此Java程序可以通過set進行迭代。因此,HashMap是快速失敗的。另一方面,HashTable提供了它鍵的枚舉。
HashTable類被當做遺留類(譯者注:Java遺留類說明)
Array與ArrayList類在以下特性中有所區別:
Arrays可以包含基礎數據類型或者對象,而ArrayList只能包含對象。
Arrays有固定長度,而ArrayList長度則是動態的。
ArrayList類提供了更多的方法和特性,比如addAll,removeAll,iterator,等等
對于一個基礎數據類型的list,集合框架使用了自動裝箱去減少編碼的工作。但針對固定長度的的基礎數據類型,這種方法會使得它們變得更慢。
ArrayList、LinkedList這兩個類都實現了List接口,但他們以下特性中又有所不同:
ArrayList是基于索引的數據結構,底層由Array支持實現。它提供了以時間復雜度為O(1)的性能隨機訪問它的元素,另一方面,LinkedList以元素列表的方式來存儲它的數據,每一個元素與它前一個和后一個元素都是相連的。對元素查詢操作的時間復雜度為O(n).
對元素的插入、添加、移除操作,與ArrayList相比,LinkedList更快,因為,當一個元素被添加到集合內部的任意位置時,LinkedList不需要重新調整數組大小或者更新索引。
LinkedList比ArrayList消耗更多的內存,因為LinkedList中每一個節點都存儲了兩個引用,一個是它前一個元素,一個是它后一個元素
也可以查看我們的文章ArrayList vs. LinkedList
Java 提供的 Comparable 接口,其中只包含一個方法,就是 compareTo。這個方法會比較兩個對象,從而得出它們的順序關系。具體來說,它會返回一個負整數,零,或一個正整數,分別表示傳入的對象小于,等于或大于已有的對象。
Java 提供的 Comparator 接口,包含兩個方法,compare 和 equals 。compare 方法比較兩個參數,得出它們的順序關系。它會返回一個負整數,零,或一個正整數,分別表示第一個參數小于,等于或大于已有的對象。equals 方法有1個參數,它用來確定參數對象是否等于這個 camparator。這個方法僅在要比較的對象也是一個 comparator,同時它的序關系與這個 comparator 相同時,才會返回 true。
PriorityQueue是一個基于優先級堆的無界隊列,它的元素都以他們的自然順序有序排列。在它創建的時候,我們可以可以提供一個比較器(Comparator)來負責PriorityQueue中元素的排序。PriorityQueue不允許null元素,不允許不提供自然排序的對象,也不允許沒有任何關聯Comparator的對象。最后,PriorityQueue不是線程安全的,在執行入隊和出隊操作它需要O(log(n))的時間復雜度。
Big-O符號簡單描述了,在一種數據結構中隨著元素的不斷增加,在最壞的情況下,一個算法的擴展或者執行能有多好。Big-O符號還可以用來描述其他的行為,比如內存消耗。由于collection集合下的類實際上都是數據結構,我們通常用Big-O符號來選擇基于時間、內存、性能前提下的最好實現去使用。Big-O符號能就大量數據的性能給出一個很好的指示。
有序數組最關鍵的優勢在于搜索的時間復雜度為 O(log n),而無序數組的時間復雜度是 O (n)。有序數組的劣勢就在于插入操作的時間復雜度為 O(n),因為較高值的元素需要挪動位置騰出空間給新元素。與之不同的是,無序數組的插入操作的時間復雜度為 O(1)。
基于應用的需求來選擇使用正確類型的集合,這對性能來說是非常重要的。例如,如果元素的大小是固定的,并且知道優先級,我們將會使用一個 Array,而不是 ArrayList。
一些集合類允許我們指定他們的初始容量。因此,如果我們知道存儲數據的大概數值,就可以避免重散列或者大小的調整。
總是使用泛型來保證類型安全,可靠性和健壯性。同時,使用泛型還可以避免運行時的 ClassCastException。
在 Map 中使用 Java Development Kit (JDK) 提供的不可變類作為一個 key,這樣可以避免 hashCode 的實現和我們自定義類的 equals 方法。
應該依照接口而不是實現來編程。
返回零長度的集合或者數組,而不是返回一個 null ,這樣可以防止底層集合是空的。
Enumeration 跟 Iterator 相比較快兩倍,而且占用更少的內存。但是,Iterator 相對于 Enumeration 更安全,因為其他線程不能修改當前迭代器遍歷的集合對象。同時,Iterators 允許調用者從底層集合中移除元素,這些 Enumerations 都沒法完成。
HashSet 是用一個 hash 表來實現的,因此,它的元素是無序的。添加,刪除和 HashSet 包括的方法的持續時間復雜度是 O(1)。
另一個方面,TreeSet 是用一個樹形結構實現的,因此,它是有序的。添加,刪除和 TreeSet 包含的方法的持續時間復雜度是 O(logn)。
總結
以上是生活随笔為你收集整理的Java知识整理——容器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java知识整理——线程
- 下一篇: Java知识整理——垃圾回收