Java06集合

13 集合

實現方法時,不同的數據結構會導致性能有很大差異。

?

13.1 集合接口

Java集合類庫將接口(interface)與實現(implementation)分離。

可以使用接口類型存放集合的應用,一旦改變了想法,可以輕松額使用另外一種不同的實現。

List<Integer> l = new ArrayList<>();

若想改為鏈表實現,只需上句為List<Integer> l = new LinkedList<>();

?

Abstract開頭的類,如AbstractQueue,是為類庫實現者設計的。

如果想要實現自己的隊列類,會發現擴展AbstractQueue類要比實現Queue接口中的方法輕松的多。

?

集合類的基本接口是Collection接口

兩個基本方法:

public interface Collection<E>
{boolean add(E element);Iterator<E> iterator();
}


iterator方法返回一個實現了Iterator接口的對象。

Iterator接口包含三個方法:

public interface Iterator<E>
{E next();boolean hasNext();void remove();
}


Java迭代器被認為是在兩個元素之間的。

當調用next時,迭代器就越過下一個元素,并返回剛剛越過的那個元素的引用。

remove方法將會刪除上次調用next方法時返回的元素。

如果調用remove之前沒有調用next將是不合法的。

?

由于CollectionIterator都是泛型接口,可以編寫任何集合類型實用方法。

?

?

?

?

?

?

13.2 具體的集合

Map結尾的類實現了Map接口;其他實現了Collection接口。

ArrayList

順序表

LinkedList

雙向鏈表

ArrayDeque

循環數組實現的雙端隊列

HashSet

沒有重復元素的無序集合

TreeSet

有序集

EnumSet

包含枚舉類型值的集

LinkedHashSet

可以記住元素插入順序的集

PriorityQueue

允許高效刪除最小元素的集合

HashMap

?

TreeMap

?

EnumMap

鍵值屬于枚舉類型

LinkedHashMap

可以記住K/V的添加次序

WeakHashMap

其值無用武之地后可以被垃圾回收器回收

IdentityHashMap

==而不是equals比較鍵值的映射表

?

?

LinkedList

interface ListIterator<E> extends Iterator<E>
{void add(E element);E previous();boolean hasPrevious();
}


set方法用一個新元素取代調用nextprevious方法返回的上一個元素。

ListIterator<String> iter = list.listIterator();

String oldValue = iter.next(); //returns first element

iter.set(newValue); //sets first element to newValue

?

當某個迭代器修改集合時,另一個迭代器對其進行遍歷,一定會出現混亂的狀況。

例如:一個迭代器指向另一個迭代器剛剛刪除的元素前面,現在這個迭代器就是無效的,并且不應該再使用。

鏈表迭代器的設計使它能夠檢測到這種修改。

如果迭代器發現它的集合被另一個迭代器修改了,或是被該集合自身的方法修改了,就會拋出一個ConcurrentModificationException

例如:

ListIterator<String> iter1 = list.listIterator();

ListIterator<String> iter2 = list.listIterator();

iter1.next();

iter1.remove();

iter2.next(); //throws ConcurrentModificationException

?

鏈表不支持隨機訪問,但支持get(int index)

get方法的小優化:如果index > size() / 2 就從列表尾端開始搜索元素。

for (int i = 0; i < list.size(); ++i)do something with list.get(i);//效率極低。出現此代碼說明用錯數據結構。

nextIndex() ?previousIndex() ?返回索引值

list.listIterator(n)返回一個迭代器,這個迭代器指向索引為n的元素前面的位置。

?

?

ArrayList

適用于getset方法。

Vector類的所有方法都是同步的,如果由一個線程訪問Vector,代碼要在同步操作上耗費大量的時間。

ArrayList方法不是同步的。

?

散列集:

散列表(hash table

散列表為每個對象計算一個整數,稱為散列碼(hash code)。

散列碼是由對象的實例域產生的一個整數。具有不同數據域的對象將產生不同的散列碼。

散列碼要能夠快速的計算出來。

?

Java中,散列表用鏈表數組實現。每個列表被稱為桶(bucket)。

?


散列碼與桶數的余數是元素的桶的索引。

?

散列沖突(hash collision

?

將桶數設置為預計元素個數的75%~150%,最好將桶數設置為一個素數,以防鍵的聚集。

標準庫使用的桶數是2的冪,默認值為16。為表大小提供的任何值都將被自動的轉換為2的下一個冪。

?

如果散列表太滿,就需要再散列(rehashed)。

創建一個雙倍桶數的表,將所有元素插入到這個新表中,然后丟棄原來的表。

裝填因子(load factor)決定何時對散列表進行再散列。

對大多數應用程序來說,裝填因子為0.75是比較合理的。

?

散列集迭代器依此訪問所有的桶,所以訪問順序是隨機的。

HashSet

?


樹集:

有序集合(sorted collection

紅黑樹(red-black tree

迭代器以排好序的順序訪問每個元素

?

添加元素到樹中要比添加到散列表中慢,但是,與將元素添加到數組或鏈表中相比還是快很多的。

TreeSet

?

對象的比較:

默認情況下,樹集假定插入的元素實現了Comparable接口。

public interface Comparable<T>
{int compareTo(T other);
}
a.compareTo(b); //相等返回0;a在前返回負值;b在前返回正值。


使用Comparable接口定義排序有局限性。

對于一個給定的類,只能夠實現這個接口一次。

如果在一個集合中需要按照部件編號進行排序,在另一個集合中卻要按照描述信息進行排序,該如何?

如果一個類沒有實現Comparable接口,又該如何?

可通過將Comparator對象傳遞給TreeSet構造器來告訴樹集使用不同的比較方法。

pubic interface Comparator<T>
{int compare(T a, T b);
}


如:

class ItemComparator implements Comparator<Item>
{public int compare(Item a, Item b){  return a.getDescription().compareTo(b.getDescription()); }
}
ItemComparator comp = new ItemComparator();
SortedSet<Item> sortByDescription = new TreeSet<>(comp);

?

比較器是比較方法的持有器,不含數據,將這種對象稱為函數對象(function object)。

函數對象通常動態定義,即定義為匿名內部類的實例。

SortedSet<Item> sortByDescription = new TreeSet<>(new
Comparator<Item>()
{public int compare(Item a, Item b)return a.getDescription().compareTo(b.getDescription());
}

?

?

隊列與雙端隊列:

ArrayDeque

?

優先級隊列:

priority queue

可以按照任意的順序插入,卻總是按照排序的順序進行檢索。

即,無論何時調用remove方法,總會獲得當前優先級隊列中最小的元素。

優先級隊列使用的是堆(heap)。

?

映射表:

Map key/value

HashMap ?TreeMap

三種視圖:

Set<K> keySet()

Collection<K> values()

Set<Map.Entry<K, V>> entrySet()

?

弱散列映射表:

WeakHashMap

如果一個值,對應鍵的唯一引用來自散列表條目時,這一數據結構將與垃圾回收器協同工作一起刪除鍵/值對。

?

連接散列集和連接映射表:

LinkedHashSet ?LinkedHashMap 用來記住插入元素項的順序。

?

鏈接散列映射表將用訪問順序而不是插入順序,對映射表條目進行迭代。

?

標識散列映射表:

IdentityHashMap

鍵的散列不是用hashCode函數來計算的,而是用System.identityHashCode方法計算。

根據對象的內存地址來計算散列碼。

兩個對象進行比較時,IdentityHashMap使用的是”==”。

在實現對象遍歷算法(如對象序列化)時,這個類非常有用,可以用來跟蹤每個對象的遍歷狀況。


13.3 集合框架

框架(framework)是一個類的集,它奠定了創建高級功能的基礎。

框架包含很多超類,這些超類擁有非常有用的功能、策略和機制。

框架使用者創建的子類可以擴展超類的功能,而不必重新創建這些基本的機制。

例如Swing就是一種用戶界面的機制。

Java集合類庫構成了集合類的框架,它為集合的實現定義了大量的接口和抽象類,并且對其中的某些機制給予了描述,例如,迭代協議。

?

如果想要實現用于多種集合類型的泛型算法,或者想要增加新的集合類型,必須了解框架。

?

集合有兩個基本接口:CollectionMap


List是一個有序集合(ordered collection


標記接口RandomAccess,檢測一個特定的集合是否支持隨機檢索。

?

集合接口有大量地方法,這些方法可以通過更基本的方法加以實現。

抽象類提供了許多這樣的例行實現。

如果實現了自己的集合類,就可能要擴展上面某個類,以便可以選擇例行操作的實現。

Java類庫支持下面幾種具體類:

?

?

視圖與包裝器:

keySet方法返回一個實現Set接口的類對象,這個類的方法對原映射表進行操作。

這種集合稱為視圖。

?

1、輕量級包裝器

Arrays類的靜態方法asList將返回一個包裝了普通Java數組的List包裝器。

Card[] cardDeck = new Card[52];

List<Card> cardList = Arrays.asList(cardDeck);

改變數組大小的所有方法都會拋出一個UnsupportedOperationException異常。

?

List<String> names = Arrays.asList(“Amy”, “Bob”, “Carl”);

這個方法調用Collections.nCopies(n, anObject)方法。

?

2、子范圍視圖

subList方法

List group2 = staff.subList(10, 20); //含首不含尾

可以將任何操作應用于子范圍。

?

對于有序集和映射表,可以使用排序順序建立子范圍。

SortedSet接口聲明了3個方法:

SortedSet<E> subSet(E from, E to);

SortedSet<E> headSet(E to);

SortedSet<E> tailSet(E from);

?

SortedMap<K, V> subSet(K from, K to);

SortedMap<K, V> headSet(K to);

SortedMap<K, V> tailSet(K from);

?

3、不可修改視圖

Collections.unmodiffiableCollection

Collections.unmodifiableList

Collections.unmodifiableSet

Collections.unmodifiableSortedSet

Collections.unmodifiableMap

Collections.unmodifiableSortedMap

?

每個方法都定義于一個接口。

這些視圖對現有集合增加了一個運行時的檢查。

如果發現試圖對集合進行修改,就拋出一個異常。

?

4、同步視圖

如果由多個線程訪問集合,就必須確保集不會被意外的破壞。

類庫的設計者使用視圖機制來確保常規集合的線程安全,而不是實現線程安全的集合類。

Map<String, Employee> map = Collections.synchronizedMap(new HashMap<String, Employee>());

?

5、檢查視圖

List<String> sateStrings = Collections.checkedList(strings, String.class);

視圖的add方法將檢測插入的對象是否屬于給定的類。如果不是,則拋出ClassCastException

?

?

批操作:

bulk operation

result.retainAll(a); //保存了交集

result.removeAll(b);

result.addAll(b);

?

集合與數組之間的轉換:

數組->集合:Arrays.asList包裝器

集合->數組:toArray()方法

staff.toArray();//返回的是Object數組,不能強制類型轉換;

staff.toArray(new String[0]);//返回的是String數組;

staff.toArray(new String[staff.size()]); //將元素一次復制到新數組中,并返回新數組

?

13.4 算法

泛型集合接口有一個很大的優點,即算法只需要實現一次。

?

排序:

Collections類中的sort方法。

這個方法假定元素實現了Comparable接口。

如果想采用其他方式對列表進行排序,可將Comparator對象作為第二個參數傳遞給sort方法。

降序:Collections.reverseOrder()方法

?

Java直接將所有元素轉入一個數組,并使用歸并排序的變體對數組進行排序,然后將排序后的序列復制回列表。

集合類庫中使用的歸并排序算法比快速排序要慢,快速排序是通用排序算法的傳統選擇。

歸并排序的優點,穩定,即不需要交換相同的元素。

?

排序的列表必須是可修改的,但不必是可以改變大小的。

·如果列表支持set,則是可修改的;

·如果列表支持addremove方法,則是可改變大小的。

?

混亂:

Collectionsshuffle算法,隨機的混排列表中元素的順序。

如果沒有實現RandomAccess接口,shuffle方法將元素復制到數組中,然后打亂數組元素的順序,最后再將打亂順序后的元素復制回列表。

?

二分查找:

i = Collections.binarySearch(c, element);

i = Collections.binarySearch(c, element, comparator);

?

二分查找對順序表有意義,如果對鏈表采用二分查找,則自動變為順序查找。

?

編寫自己的算法:

如果編寫自己的算法,應該盡可能的使用接口,而不要使用具體的實現。

?

13.5 遺留的集合

Java程序設計語言自問世以來就存在的集合:Hashtable ?Properties ?Vector ?Stack ?BitSet

?

Hashtable

HashMap類的作用一樣,擁有相同的接口。

Hashtable的方法也是同步的。

?

枚舉:

使用Enumeration接口對元素序列進行遍歷。

兩個方法:hasMoreElementsnextElement

靜態方法Collections.enumeration將產生一個枚舉對象,枚舉集合中的元素。

?

屬性映射表:

property map

·鍵和值都是字符串;

·表可以保存到一個文件中,也可以從文件中加載

·使用一個默認的輔助表。

實現屬性映射表的類稱為Properties

通常用于程序的特殊配置選項。

?

棧:

stack

?

位集:

BitSet類提供了一個便于讀取、設置或清除各個位的接口。

C++中的bitset功能一樣。

?

?

?

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/387288.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/387288.shtml
英文地址,請注明出處:http://en.pswp.cn/news/387288.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Tensorflow驗證碼識別應用

簡單的Tensorflow驗證碼識別應用&#xff0c;供大家參考&#xff0c;具體內容如下 1.Tensorflow的安裝方式簡單,在此就不贅述了. 2.訓練集訓練集以及測試及如下(純手工打造,所以數量不多): 3.實現代碼部分(參考了網上的一些實現來完成的) main.py(主要的神經網絡代碼) ?123456…

9 文件系統管理

9.1 回顧分區和文件系統 分區類型 主分區&#xff1a;總共最多只能分四個 擴展分區&#xff1a;只能有一個&#xff0c;主分區加擴展分區最多有四個&#xff0c;必須再劃分成邏輯分區才能使用。 邏輯分區&#xff1a;在擴展分區中劃分的 IDE硬盤最多支持59個邏輯分區 SCSI…

Linux 桌面玩家指南:09. X Window 的奧秘

Linux 桌面玩家指南&#xff1a;09. X Window 的奧秘 原文:Linux 桌面玩家指南&#xff1a;09. X Window 的奧秘特別說明&#xff1a;要在我的隨筆后寫評論的小伙伴們請注意了&#xff0c;我的博客開啟了 MathJax 數學公式支持&#xff0c;MathJax 使用$標記數學公式的開始和結…

Storm教程1理論介紹

流式計算的歷史: 早在7、8年前諸如UC伯克利、斯坦福等大學就開始了對流式數據處理的研究&#xff0c;但是由于更多的關注于金融行業的業務場景或者互聯網流量監控的業務場景&#xff0c;以及當時互聯網數據場景的限制&#xff0c;造成了研究多是基于對傳統數據庫處理的流式化&…

梯度下降原理及Python實現

梯度下降算法是一個很基本的算法&#xff0c;在機器學習和優化中有著非常重要的作用&#xff0c;本文首先介紹了梯度下降的基本概念&#xff0c;然后使用python實現了一個基本的梯度下降算法。梯度下降有很多的變種&#xff0c;本文只介紹最基礎的梯度下降&#xff0c;也就是批…

dagger2的初次使用

一、使用前準備 1、打開app的build.gradle文件&#xff1a; 頂部停用apt插件&#xff1a; //添加如下代碼&#xff0c;應用apt插件 apply plugin: com.neenbedankt.android-apt dependencies中添加依賴&#xff1a; //Dagger2compile com.google.dagger:dagger:2.4apt com.goog…

Storm教程2安裝部署

Storm 安裝部署 部署Storm集群需要依次完成的安裝步驟&#xff1a; 1.安裝jdk6及以上版本;   2. 搭建Zookeeper集群&#xff1b;   3. 安裝Storm依賴庫&#xff1b;   4. 下載并解壓Storm發布版本&#xff1b;   5. 修改storm.yaml配置文件&#xff1b;   6…

matplotlib一些常用知識點的整理,

本文作為學習過程中對matplotlib一些常用知識點的整理&#xff0c;方便查找。 強烈推薦ipython 無論你工作在什么項目上&#xff0c;IPython都是值得推薦的。利用ipython --pylab&#xff0c;可以進入PyLab模式&#xff0c;已經導入了matplotlib庫與相關軟件包&#xff08;例如…

JAVA課程09

package 月份輸出;import java.util.*;public class 月份輸出 {public static void main(String[] args) {// TODO Auto-generated method stubScanner sc new Scanner(System.in);int s sc.nextInt();String a[] {"January","February","March&q…

Storm教程3編程接口

Spouts Spout是Stream的消息產生源&#xff0c;Spout組件的實現可以通過繼承BaseRichSpout類或者其他Spout類來完成&#xff0c;也可以通過實現IRichSpout接口來實現。 需要根據情況實現Spout類中重要的幾個方法有&#xff1a; open方法 當一個Task被初始化的時候會調用此…

梳理操作系統概論

1、用一張圖總結操作系統的結構、功能特征、采用的技術和提供服務方式等。 2、用一張圖描述CPU的工作原理。 3、用一張圖描述系統程序與應用程序、特權指令與非特權指令、CPU狀態、PSW及中斷是如何協同工作的&#xff1f; 轉載于:https://www.cnblogs.com/ljgljg/p/10503190.ht…

機器學習01簡介

Machine Learning 是人工智能的核心&#xff0c;主要使用歸納、綜合而不是演繹。 讓計算機模擬人類行為&#xff0c;以獲取新的知識或技能 重新組織已有的知識結構使之不斷改善自身性能 一個程序能從經驗 E 中學習&#xff0c;解決任務 T&#xff0c;達到性能度量值P&#xf…

位置指紋法的實現(KNN)

基本原理 位置指紋法可以看作是分類或回歸問題&#xff08;特征是RSS向量&#xff0c;標簽是位置&#xff09;&#xff0c;監督式機器學習方法可以從數據中訓練出一個從特征到標簽的映射關系模型。kNN是一種很簡單的監督式機器學習算法&#xff0c;可以用來做分類或回歸。 對于…

室內定位系列 ——WiFi位置指紋(譯)

摘要 GPS難以解決室內環境下的一些定位問題&#xff0c;大部分室內環境下都存在WiFi&#xff0c;因此利用WiFi進行定位無需額外部署硬件設備&#xff0c;是一個非常節省成本的方法。然而WiFi并不是專門為定位而設計的&#xff0c;傳統的基于時間和角度的定位方法并不適用于WiFi…

機器學習02線性回歸、多項式回歸、正規方程

單變量線性回歸&#xff08;Linear Regression with One Variable&#xff09; 預測器表達式&#xff1a; 選擇合適的參數&#xff08;parameters&#xff09;θ0 和 θ1&#xff0c;其決定了直線相對于訓練集的準確程度。 建模誤差&#xff08;modeling error&#xff09;&a…

最大乘積

給定一個無序數組&#xff0c;包含正數、負數和0&#xff0c;要求從中找出3個數的乘積&#xff0c;使得乘積最大&#xff0c;要求時間復雜度&#xff1a;O(n)&#xff0c;空間復雜度&#xff1a;O(1) def solve():n input()a input().split()for i in range(len(a)):a[i] in…

機器學習03Logistic回歸

邏輯回歸 &#xff08;Logistic Regression&#xff09; 目前最流行&#xff0c;使用最廣泛的一種學習算法。 分類問題&#xff0c;要預測的變量 y 是離散的值。 邏輯回歸算法的性質是&#xff1a;它的輸出值永遠在 0 到 1 之間。 邏輯回歸模型的假設是&#xff1a; 其中&a…

基礎架構系列匯總

為了方便查找&#xff0c;把基礎架構系統文章按時間正序整理了一下&#xff0c;記錄如下&#xff1a; 1. 基礎架構之日志管理平臺搭建及java&net使用 2. 基礎架構之日志管理平臺及釘釘&郵件告警通知 3. 基礎架構之分布式配置中心 4. 基礎架構之分布式任務平臺 5. 基礎架…

CNN理解比較好的文章

什么是卷積神經網絡&#xff1f;為什么它們很重要&#xff1f; 卷積神經網絡&#xff08;ConvNets 或者 CNNs&#xff09;屬于神經網絡的范疇&#xff0c;已經在諸如圖像識別和分類的領域證明了其高效的能力。卷積神經網絡可以成功識別人臉、物體和交通信號&#xff0c;從而為機…

Windows 安裝Angular CLI

1、安裝nvm npm cnpm nrm&#xff08;onenote筆記上有記錄&#xff09; 參考&#xff1a;https://blog.csdn.net/tyro_java/article/details/51232458 提示&#xff1a;如果發現配置完后&#xff0c;出現類似“npm不是內部命令……”等信息。 可采取如下措施進行解決—— 檢查環…