天天看點

java retainall雙連結清單_java集合 讀書筆記

Java庫中的具體集合和整個集合架構

連結清單

數組清單

散列集

樹集

隊列與雙端隊列

優先級隊列

映射表

Java庫中的具體集合和整個集合架構

連結清單(LinkedList)

資料和數組清單有一個重大缺陷,因為删除一個或者添加一個元素都需要付出很大的代價,原因是出于被删除或被添加的元素後面的所有元素都要被移動,而連結清單就解決了這個問題。删除添加隻需要對被删除元素附近的節點更新一下即可。但因為結果原因,如果要對集合經常随機通路,則最好使用arraylist.

LinkedList.add方法是把元素添加到尾部,如果想添加到中間,就的借助疊代器。因為linkedlist裡面的元素是有序的,是以他的疊代器裡面是有添加方法的,而集(set)裡面的元素完全無序,是以他的疊代器接口就沒有add方法。ListIterator裡面的add方法就可以把元素添加到疊代器位置之前。。

如果有多個疊代器在一個集合上疊代,集合被一個疊代器或者自身修改,那麼疊代器都沒有意義了,就會發出異常!

清單不支援快速随機通路,如果想通路第N個元素,那就就的才能夠頭開始越過n-1個元素,是以在這種情況下一般不選擇連結清單。但是盡管如此LinkedListjava類庫還是提供了理論上存在争議的一些方法。比如采用整數索引通路元素,get(n)但是這個效率肯定不高,previousIndex,nextIndex這個效率還是很高的。

數組清單(ArrayList)

ArrayList實作了list接口,而且對于get,set方法随機通路每個元素是非常的效率,封裝了一個動态再配置設定的對象數組。

散列集(hashSet)

散列碼由hashcode方法生成,應該于equals方法相容,就是說如果a.equals(b)為true,那麼a,b的散列碼一定相同,如果自己定義類就應該負責實作這個類的hashCode方法。裡面的元素是沒有順序的,而且元素不能重複。疊代器也是随機的周遊元素。

數集(treeSet)

與散列集不同的是,添加完元素後,元素會按照樹結構把元素自動有序的排列起來,這樣便利的時候得到的是已經排好序列的元素清單。當然添加元素的速度要比散列集慢點,但是還是比連結清單和數組的正确位置上要快點。

隊列與雙端隊列

隊列java.util.Queue 雙頭隊列java.util.Deque可以在頭部或尾部添加删除元素。

優先級隊列(priority queue)

元素可以随便插入隊列。也就是說remove的時候一定是優先級最小的元素。優先級隊列使用了一個優雅且高效的資料結構堆(heap),這是一個可以自我調整的二叉樹,添加删除操作,可以讓最小的元素移動到跟。舉個例子更好的了解,他不是把全部元素排序,而是隻是把最小的放在的最頭上面。TreeSet卻是把全部排序,是以優先級隊列速度要比treeset快。

PriorityQueuepq = new PriorityQueue(); pq.add(new GregorianCalendar(1906, Calendar.DECEMBER, 9)); // G. Hopper pq.add(new GregorianCalendar(1815, Calendar.DECEMBER, 10)); // A. Lovelace pq.add(new GregorianCalendar(1903, Calendar.DECEMBER, 3)); // J. von Neumann pq.add(new GregorianCalendar(1910, Calendar.JUNE, 22)); // K. Zuse System.out.println("Iterating over elements..."); for (GregorianCalendar date : pq) System.out.println(date.get(Calendar.YEAR)); System.out.println("Removing elements..."); while (!pq.isEmpty()) System.out.println(pq.remove().get(Calendar.YEAR));

結果

Iterating over elements...

1815

1906

1903

1910

Removing elements...

1815

1903

1906

1910

映射表(hashMap TreeMap)

散列映射對鍵進行散列,而樹映射表用鍵的整體順序對元素進行排列,隻作用于鍵,對關聯的值不能進行散列和比較。這裡有3個試圖,鍵集,值集合,鍵值對集。

SetkeySet()

Collectionvalues()

Set> entrySet()

for(String key:keys)//周遊鍵集

{

do something with key

}

//周遊對集

for(Map.Entryemtry : staff-emtrySet()){

String key=entry.getKey();

Employee value= entry.getValue();

do something with key,value

}

專業集與映射表類

弱散列映射表(weakHashMap)

有些值的鍵被引用一次後就不用了如果不明确的删除,垃圾收集器收集器又不會自動收集垃圾,是以就用到了弱散列映射表。

連結散列集和連結映射表(linkedhashset,linkedhashmap)

這樣就能記住插入元素項的順序。周遊的時候就能按照插入的順序周遊。 當然也可以按照存取順序周遊,當用get or put方法,那麼這個被取出或者放進去的元素就會被從目前位置去掉,然後放到最後面。這樣有利于實施一個 最近最少使用的cache。

枚舉集與枚舉映射集(EnumSet,EnumMap)

EnumSet是一個枚舉類型元素集的高效實作。 由于枚舉類型隻有有限個執行個體, 是以EnumSet内部用位序實作,如果對應的值集中,則相應的位置為1.

enum Weekday {MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY,SUNDAY};

EnumSetalways = EnumSet.allOf(Weekday.class);

EnumSetnever = EnumSet.noneOf(Weekday.class);

EnumSetworkday= EnumSet.range(Weekday.MONDAY, Weekday.FRIDAY);

EnumSetmwf = EnumSet.of(Weekday.MONDAY, Weekday.WEDNESDAY, Weekday.FRIDAY);

EnumMap

EnumMappersonInCharge = new EnumMap(Weekday.class);

辨別散列映射表(IdentityHashMap)

鍵的散列值不是用hashcode計算的,而是用System.identityHashCode計算的,這是object.hashCode方法根據對象的記憶體位址來計算散列碼時用的方式。對兩個對象進行比較時,不用equals,而是==。也就是說不同的鍵對象,即使内容相同,也被視為不同的對象。

視圖與包裝器

Arrays類的靜态方法asList将傳回一個包裝了普通java數組的list包裝器。

Card[] cardDeck = new Card[52];

ListcardList = Arrays.asList(cardDeck);

這是個視圖對象,可以使用get,set方法,但是添加删除都會抛出異常。

Collections.nCopies(n,anObject)建立一個包含n個元素的list,每個元素都是一個anObject.

Collections.singleton(anObject)傳回一個視圖對象,實作了set接口,不可修改的單元素集。

subList(),subSet,headSet,tailSet,subMap,headMap,tailMap方法可以得到相應集合的子範圍,而且子範圍上的修改直接反應到原集合上。

Collections.unmodifiableCollection,Collections.unmodifiableList,Collections.unmodifiableSet,Collections.unmodifiableSortedSet,

Collections.unmodifiableMap,Collections.unmodifiableSortedMap可以得到不可更改視圖,隻能讀不能修改。但是原集合依然可以修改。

Collections.synchronizedMap可以得到線程安全的同步視圖,這樣就可以多線程通路同步視圖了,get,put這種操作都被串行操作,是線程安全的。

被檢查視圖可以檢測是否有classCast錯誤例子如下:

ArrayListstrings=new ArrayList(); ArrayList rawList = strings;//get warning only, not an error, for compatibility with legacy code. rawList.add(new Date());// now String contains a Date object!! //這個錯誤的指令在運作的時候是檢測不到的。隻有在稍後的另一部分代碼中那個調用get,并将結果轉化為string,才會抛出ClassCastException錯誤異常 ListsafeStrings = Collections.checkedList(strings,String.class); ArrayList rawList = safeStrings; rawList.add(new Date());//Checked list throws a ClassCastException

這裡還有一些批操作

Setresult=new HashSet(a);

result.retainAll(b)在result保留a與b中出現的元素。就是交集。

removeAll,allAll

集合與數組之間的轉化

String[] values = ...;

HashSetstaff= new HashSet(Arrays.asList(values));

String[] values = staff.toArray(new String[staff.size()]);

算法

Collections.sort(staff,itemComparator);

Collections.sort(staff,Collections.reverseOrder(itemComparator));

Collections.schuffle(ArrayList);随機混排清單裡面的元素。

Collecitions.binarySearch(c,element),Collections.binarySearch(c,element,comparator);但是前提是集合必須是有序的而且是支援随機通路的。否則不是有序的就出異常,不是随機通路的,效率非常低就跟線性查找一樣的效率了,如果找不到對應元素,那麼可以根據範圍的負值索引,插入這個元素,if(i<0) c.add(-i-1,element); i是傳回的負值索引。

min,max,copy,fill,addAll,indexOfSubList,lastIdexOfSubList,swap,reverse,rotate,frequency,disjoint方法。

遺留的集合

hashTable跟hashMap作用一樣,而且是同步的,但是如果對同步性或者與遺留代碼的相容性沒有任何要求,就應該使用hashMap.

枚舉Enumeration有兩個方法,hasMoreElements,nextElement類似與iterator接口的hasNext,next方法。

屬性映射表(perperty map)比較特殊,有3個特性:鍵與值都是字元串,可以儲存到一個檔案中,也可以從檔案中加載。還有一個預設的輔助表。

位集(BitSet)用來存放一個位序列,由于位集将位包裝在位元組裡面,是以比使用Boolean對象的ArrayList更加有效。