日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

java集合是wftc_Java集合

發布時間:2024/10/6 java 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java集合是wftc_Java集合 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、集合的由來

通常,我們的程序需要根據程序運行時才知道創建多少個對象。但若非程序運行,程序開發階段,我們根本不知道到底需要多少個數量的對象,甚至不知道它的準確類型。為了滿足這些常規的編程需要,我們要求能在任何時候,任何地點創建任意數量的對象,而這些對象用什么來容納呢?我們首先想到了數組,但是數組只能放統一類型的數據,而且其長度是固定的,那怎么辦呢?集合便應運而生了!

二、集合是什么?

Java集合類存放于 java.util 包中,是一個用來存放對象的容器。

注意:①、集合只能存放對象。比如你存一個 int 型數據 1放入集合中,其實它是自動轉換成 Integer 類后存入的,Java中每一種基本類型都有對應的引用類型。

②、集合存放的是多個對象的引用,對象本身還是放在堆內存中。

③、集合可以存放不同類型,不限數量的數據類型

數組和集合的比較

數組不是面向對象的,存在明顯的缺陷,集合彌補了數組的缺點,比數組更靈活更實用,而且不同的集合框架類可適用不同場合。如下:

1:數組能存放基本數據類型和對象,而集合類存放的都是對象的引用,而非對象本身!

2:數組容易固定無法動態改變,集合類容量動態改變。

3:數組無法判斷其中實際存有多少元素,length只告訴了數組的容量,而集合的size()可以確切知道元素的個數

4:集合有多種實現方式和不同適用場合,不像數組僅采用順序表方式

5:集合以類的形式存在,具有封裝、繼承、多態等類的特性,通過簡單的方法和屬性即可實現各種復雜操作,大大提高了軟件的開發效率

三、Java 集合框架圖

四、集合詳解

①、Iterator:迭代器,它是Java集合的頂層接口(不包括 map 系列的集合,Map接口 是 map 系列集合的頂層接口)

Object next():返回迭代器剛越過的元素的引用,返回值是 Object,需要強制轉換成自己需要的類型

boolean hasNext():判斷容器內是否還有可供訪問的元素

void remove():刪除迭代器剛越過的元素

所以除了 map 系列的集合,我們都能通過迭代器來對集合中的元素進行遍歷。

注意:我們可以在源碼中追溯到集合的頂層接口,比如 Collection 接口,可以看到它繼承的是類 Iterable

那這就得說明一下 Iterator 和 Iterable 的區別:

Iterable :存在于 java.lang 包中。

我們可以看到,里面封裝 Iterator接口。所以只要實現了只要實現了Iterable接口的類,就可以使用Iterator迭代器了。

Iterator :存在于 java.util 包中。核心的方法next(),hasnext(),remove()。

這里我們引用一個Iterator 的實現類 ArrayList 來看一下迭代器的使用:暫時先不管 List 集合是什么,只需要看看迭代器的用法就行了

1 //產生一個 List 集合,典型實現為 ArrayList。

2 List list = newArrayList();3 //添加三個元素

4 list.add("Tom");5 list.add("Bob");6 list.add("Marry");7 //構造 List 的迭代器

8 Iterator it =list.iterator();9 //通過迭代器遍歷元素

10 while(it.hasNext()){11 Object obj =it.next();12 System.out.println(obj);13 }

②、Collection:List 接口和 Set 接口的父接口

看一下 Collection 集合的使用例子:

1 //我們這里將 ArrayList集合作為 Collection 的實現類

2 Collection collection = newArrayList();3

4 //添加元素

5 collection.add("Tom");6 collection.add("Bob");7

8 //刪除指定元素

9 collection.remove("Tom");10

11 //刪除所有元素

12 Collection c = newArrayList();13 c.add("Bob");14 collection.removeAll(c);15

16 //檢測是否存在某個元素

17 collection.contains("Tom");18

19 //判斷是否為空

20 collection.isEmpty();21

22 //利用增強for循環遍歷集合

23 for(Object obj : collection){24 System.out.println(obj);25 }26 //利用迭代器 Iterator

27 Iterator iterator =collection.iterator();28 while(iterator.hasNext()){29 Object obj =iterator.next();30 System.out.println(obj);31 }

③、List :有序,可以重復的集合。

由于 List 接口是繼承于 Collection 接口,所以基本的方法如上所示。

1、List 接口的三個典型實現:

①、List list1 = new ArrayList();

底層數據結構是數組,查詢快,增刪慢;線程不安全,效率高

②、List list2 = new Vector();

底層數據結構是數組,查詢快,增刪慢;線程安全,效率低,幾乎已經淘汰了這個集合

③、List list3 = new LinkedList();

底層數據結構是鏈表,查詢慢,增刪快;線程不安全,效率高

怎么記呢?我們可以想象:

數組就像身上編了號站成一排的人,要找第10個人很容易,根據人身上的編號很快就能找到。但插入、刪除慢,要望某個位置插入或刪除一個人時,后面的人身上的編號都要變。當然,加入或刪除的人始終末尾的也快。

鏈表就像手牽著手站成一圈的人,要找第10個人不容易,必須從第一個人一個個數過去。但插入、刪除快。插入時只要解開兩個人的手,并重新牽上新加進來的人的手就可以。刪除一樣的道理。

2、除此之外,List 接口遍歷還可以使用普通 for 循環進行遍歷,指定位置添加元素,替換元素等等。

1 //產生一個 List 集合,典型實現為 ArrayList

2 List list = newArrayList();3 //添加三個元素

4 list.add("Tom");5 list.add("Bob");6 list.add("Marry");7 //構造 List 的迭代器

8 Iterator it =list.iterator();9 //通過迭代器遍歷元素

10 while(it.hasNext()){11 Object obj =it.next();12 //System.out.println(obj);

13 }14

15 //在指定地方添加元素

16 list.add(2, 0);17

18 //在指定地方替換元素

19 list.set(2, 1);20

21 //獲得指定對象的索引

22 int i=list.indexOf(1);23 System.out.println("索引為:"+i);24

25 //遍歷:普通for循環

26 for(int j=0;j

④、Set:典型實現 HashSet()是一個無序,不可重復的集合

1、Set hashSet = new HashSet();

①、HashSet:不能保證元素的順序;不可重復;不是線程安全的;集合元素可以為 NULL;

②、其底層其實是一個數組,存在的意義是加快查詢速度。我們知道在一般的數組中,元素在數組中的索引位置是隨機的,元素的取值和元素的位置之間不存在確定的關系,因此,在數組中查找特定的值時,需要把查找值和一系列的元素進行比較,此時的查詢效率依賴于查找過程中比較的次數。而 HashSet 集合底層數組的索引和值有一個確定的關系:index=hash(value),那么只需要調用這個公式,就能快速的找到元素或者索引。

③、對于 HashSet: 如果兩個對象通過 equals() 方法返回 true,這兩個對象的 hashCode 值也應該相同。

1、當向HashSet集合中存入一個元素時,HashSet會先調用該對象的hashCode()方法來得到該對象的hashCode值,然后根據hashCode值決定該對象在HashSet中的存儲位置

1.1、如果 hashCode 值不同,直接把該元素存儲到 hashCode() 指定的位置

1.2、如果 hashCode 值相同,那么會繼續判斷該元素和集合對象的 equals() 作比較

1.2.1、hashCode 相同,equals 為 true,則視為同一個對象,不保存在 hashSet()中

1.2.2、hashCode 相同,equals 為 false,則存儲在之前對象同槽位的鏈表上,這非常麻煩,我們應該約束這種情況,即保證:如果兩個對象通過 equals() 方法返回 true,這兩個對象的 hashCode 值也應該相同。

注意:每一個存儲到 哈希 表中的對象,都得提供 hashCode() 和 equals() 方法的實現,用來判斷是否是同一個對象對于 HashSet 集合,我們要保證如果兩個對象通過 equals() 方法返回 true,這兩個對象的 hashCode 值也應該相同。

常見的 hashCode()算法:

2、Set linkedHashSet = new LinkedHashSet();

①、不可以重復,有序

因為底層采用 鏈表 和 哈希表的算法。鏈表保證元素的添加順序,哈希表保證元素的唯一性

3、Set treeSet = new TreeSet();

TreeSet:有序;不可重復,底層使用 紅黑樹算法,擅長于范圍查詢。

如果使用 TreeSet() 無參數的構造器創建一個 TreeSet 對象, 則要求放入其中的元素的類必須實現 Comparable 接口所以, 在其中不能放入 null 元素

必須放入同樣類的對象.(默認會進行排序) 否則可能會發生類型轉換異常.我們可以使用泛型來進行限制

1 Set treeSet = newTreeSet();2 treeSet.add(1); //添加一個 Integer 類型的數據

3 treeSet.add("a"); //添加一個 String 類型的數據

4 System.out.println(treeSet); //會報類型轉換異常的錯誤

自動排序:添加自定義對象的時候,必須要實現 Comparable 接口,并要覆蓋 compareTo(Object obj) 方法來自定義比較規則

如果 this > obj,返回正數 1

如果 this < obj,返回負數 -1

如果 this = obj,返回 0 ,則認為這兩個對象相等

兩個對象通過 Comparable 接口 compareTo(Object obj) 方法的返回值來比較大小, 并進行升序排列

定制排序: 創建 TreeSet 對象時, 傳入 Comparator 接口的實現類.?要求: Comparator 接口的 compare 方法的返回值和 兩個元素的 equals() 方法具有一致的返回值

1 public classTreeSetTest {2 public static voidmain(String[] args) {3 Person p1 = new Person(1);4 Person p2 = new Person(2);5 Person p3 = new Person(3);6

7 Set set = new TreeSet<>(newPerson());8 set.add(p1);9 set.add(p2);10 set.add(p3);11 System.out.println(set); //結果為[1, 2, 3]

12 }13

14 }15

16 class Person implements Comparator{17 public intage;18 publicPerson(){}19 public Person(intage){20 this.age =age;21 }22 @Override23 /***24 * 根據年齡大小進行排序25 */

26 public intcompare(Person o1, Person o2) {27 //TODO Auto-generated method stub

28 if(o1.age >o2.age){29 return 1;30 }else if(o1.age

37 @Override38 publicString toString() {39 //TODO Auto-generated method stub

40 return ""+this.age;41 }42 }

當需要把一個對象放入 TreeSet 中,重寫該對象對應的 equals() 方法時,應保證該方法與 compareTo(Object obj) 方法有一致的結果

以上三個 Set 接口的實現類比較:

共同點:

1、都不允許元素重復

2、都不是線程安全的類,解決辦法:Set set = Collections.synchronizedSet(set 對象)

不同點:

1、HashSet:不保證元素的添加順序,底層采用 哈希表算法,查詢效率高。判斷兩個元素是否相等,equals() 方法返回 true,hashCode() 值相等。即要求存入 HashSet 中的元素要覆蓋 equals() 方法和 hashCode()方法

2、LinkedHashSet:HashSet 的子類,底層采用了 哈希表算法以及 鏈表算法,既保證了元素的添加順序,也保證了查詢效率。但是整體性能要低于 HashSet

3、TreeSet:不保證元素的添加順序,但是會對集合中的元素進行排序。底層采用 紅-黑 樹算法(樹結構比較適合范圍查詢)

⑤、Map:key-value 的鍵值對,key 不允許重復,value 可以

1、嚴格來說 Map 并不是一個集合,而是兩個集合之間 的映射關系。

2、這兩個集合沒每一條數據通過映射關系,我們可以看成是一條數據。即 Entry(key,value)。Map 可以看成是由多個 Entry 組成。

3、因為 Map 集合即沒有實現于 Collection 接口,也沒有實現 Iterable 接口,所以不能對 Map 集合進行 for-each 遍歷。

1 Map hashMap = new HashMap<>();2 //添加元素到 Map 中

3 hashMap.put("key1", "value1");4 hashMap.put("key2", "value2");5 hashMap.put("key3", "value3");6 hashMap.put("key4", "value4");7 hashMap.put("key5", "value5");8

9 //刪除 Map 中的元素,通過 key 的值

10 hashMap.remove("key1");11

12 //通過 get(key) 得到 Map 中的value

13 Object str1 = hashMap.get("key1");14

15 //可以通過 添加 方法來修改 Map 中的元素

16 hashMap.put("key2", "修改 key2 的 Value");17

18 //通過 map.values() 方法得到 Map 中的 value 集合

19 Collection value =hashMap.values();20 for(Object obj : value){21 //System.out.println(obj);

22 }23

24 //通過 map.keySet() 得到 Map 的key 的集合,然后 通過 get(key) 得到 Value

25 Set set =hashMap.keySet();26 for(String str : set){27 Object obj =hashMap.get(str);28 //System.out.println(str+"="+obj);

29 }30

31 //通過 Map.entrySet() 得到 Map 的 Entry集合,然后遍歷

32 Set> entrys =hashMap.entrySet();33 for(Map.Entryentry: entrys){34 String key =entry.getKey();35 Object value2 =entry.getValue();36 System.out.println(key+"="+value2);37 }38

39 System.out.println(hashMap);

map常用的實現類:

HashMap、TreeMap、LinkedHashMap、Hashtable等

HashMap:鍵值對,key不能重復,但是value可以重復;key的實現就是HashSet;value對應著放;允許null的鍵或值;

Hashtable:線程安全的,不允許null的鍵或值;

Properties::key和value都是String類型,用來讀配置文件;

TreeMap:對key排好序的Map; key 就是TreeSet, value對應每個key; key要實現Comparable接口或TreeMap有自己的構造器;

LinkedHashMap: 此實現與 HashMap 的不同之處在于,后者維護著一個運行于所有條目的雙重鏈接列表。存儲的數

據是有序的。

⑥、Map 和 Set 集合的關系

1、都有幾個類型的集合。HashMap 和 HashSet ,都采 哈希表算法;TreeMap 和 TreeSet 都采用 紅-黑樹算法;LinkedHashMap 和 LinkedHashSet 都采用 哈希表算法和紅-黑樹算法。

2、分析 Set 的底層源碼,我們可以看到,Set 集合 就是 由 Map 集合的 Key 組成。

總結:

結構圖詳解:

發現一個特點,上述所有的集合類,除了 map 系列的集合,即左邊集合都實現了?Iterator?接口,這是一個用于遍歷集合中元素的接口,主要hashNext(),next(),remove()三種方法。它的一個子接口?ListIterator?在它的基礎上又添加了三種方法,分別是 add(),previous(),hasPrevious()。也就是說如果實現 Iterator 接口,那么在遍歷集合中元素的時候,只能往后遍歷,被遍歷后的元素不會再被遍歷到,通常無序集合實現的都是這個接口,比如HashSet;而那些元素有序的集合,實現的一般都是 LinkedIterator接口,實現這個接口的集合可以雙向遍歷,既可以通過next()訪問下一個元素,又可以通過previous()訪問前一個 元素,比如ArrayList。

還有一個特點就是抽象類的使用。如果要自己實現一個集合類,去實現那些抽象的接口會非常麻煩,工作量很大。這個時候就可以使用抽象類,這些抽象類中給我們提供了許多現成的實現,我們只需要根據自己的需求重寫一些方法或者添加一些方法就可以實現自己需要的集合類,工作量大大降低。

HashMap特點:

Map 主要用于存儲鍵(key)值(value)對,根據鍵得到值,因此鍵不允許重復,但允許值重復。

HashMap 是一個最常用的Map,它根據鍵的HashCode 值存儲數據,根據鍵可以直接獲取它的值,具有很快的訪問速度。

HashMap最多只允許一條記錄的鍵為Null;允許多條記錄的值為 Null;

HashMap不支持線程的同步,即任一時刻可以有多個線程同時寫HashMap;可能會導致數據的不一致。如果需要同步,可以用 Collections的synchronizedMap方法使HashMap具有同步的能力。

HashMap實現原理---散列

Hash哈希算法的意義在于提供了一種快速存取數據的方法,它用一種算法建立鍵值與真實值之間的對應關系。散列表又稱為哈希表。散列表算法的基本思想是:以結點的關鍵字為自變量,通過一定的函數關系(散列函數)計算出對應的函數值,以這個值作為該結點存儲在散列表中地址。

當散列表中的元素存放太滿,就必須進行再散列,將產生一個新的散列表,所有元素存放到新的散列表中,原先的散列表將被刪除。在Java語言中,通過負載因子(load factor)來決定何時對散列表進行再散列。例如:如果負載因子0.75,當散列表中已經有75%位置已經放滿,那么將進行再散列。

負載因子越高(越接近1.0),內存的使用效率越高,元素的尋找時間越長。負載因子越低(越接近0.0),元素的尋找時間越短,內存浪費越多。

何時需重寫equals?

當一個類有自己特有的“邏輯相等”概念(不同于對象身份的概念);

Object類僅僅提供了一個對引用的比較,如果兩個引用不是同一個那就返回false,這是無法滿足大多數對象比較的需要的,所以要覆蓋;

使用==操作符檢查實參是否為指向對象的引用”

使用instanceof操作符檢查實參是否為正確的類型

把實參轉換到正確的類型;

對于該類中每一個“關鍵”域,檢查實參中的域與當前對象中對應的域值是否匹 配。對于既不是float也不是double類型的基本類型的域,可以使用==操作符 進行比較;對于對象引用類型的域,可以遞歸地調用所引用的對象的equals方法,對于float和double類型的域,先轉換成int或long類型的值,然后使用==操作符比較;

當你編寫完成了equals方法之后,應該問自己三個問題:它是否是對稱的、傳 遞的、一致的? 如果答案是否定的,那么請找到 這些特性未能滿足的原因,再修改equals方法的代碼

equals()和hashCode()同時覆寫

尤其強調當一個對象被當作鍵值(或索引)來使用的時候要重寫這兩個方法;

覆寫equals后,兩個不同實例可能在邏輯上相等,但是根據Object.hashCode方法卻產生不同的散列碼,違反“相等的對象必須具有相等的散列碼”。

導致,當你用其中的一個作為鍵保存到hashMap、hasoTable或hashSet中,再以“相等的”找另 一個作為鍵值去查找他們的時候,則根本找不到

不同類型的hashCode取值

如果該域是布爾型的,計算(f?0:1)

如果是char,short,byte或int,計算(int)f

如果是long類型,計算(int)(f^(f>>>32))

如果是float類型,計算Float.floatToIntBits(f)

如果是double類型,計算Dobule.doubleToLongBits(f)

如果該域是一個對象引用,遞歸調用hashCode

如果該域是一個數組,則把每個元素當做單獨的域來處理,對每個重要的元素計算一個散列碼,

Map集合比較:

HashMap的存入順序和輸出順序無關。

LinkedHashMap 則保留了鍵值對的存入順序。

TreeMap則是對Map中的元素進行排序。

因為HashMap和LinkedHashMap 存儲數據的速度比直接使用TreeMap 要快,存取效率要高。

當完成了所有的元素的存放后,我們再對整個的Map中的元素進行排序。這樣可以提高整個程序的運行的效率,縮短執行時間。

注意:TreeMap中是根據鍵(Key)進行排序的。而如果我們要使用TreeMap來進行正常的排序的話,Key 中存放的對象必須實現Comparable 接口。

Map常用方法:

Object put(Object key,Object value):用來存放一個鍵-值對Map中

Object remove(Object key):根據key(鍵),移除鍵-值對,并將值返回

void putAll(Map mapping) :將另外一個Map中的元素存入當前的Map中

void clear() :清空當前Map中的元素

Object get(Object key) :根據key(鍵)取得對應的值

boolean containsKey(Object key) :判斷Map中是否存在某鍵(key)

boolean containsValue(Object value):判斷Map中是否存在某值(value)

public Set keySet() :返回所有的鍵(key),并使用Set容器存放

public Collection values() :返回所有的值(Value),并使用Collection存放

public Set entrySet() :返回一個實現 Map.Entry 接口的元素 Set

1.ArrayList: 元素單個,效率高,多用于查詢

2.Vector: 元素單個,線程安全,多用于查詢

3.LinkedList:元素單個,多用于插入和刪除

4.HashMap: 元素成對,元素可為空

5.HashTable: 元素成對,線程安全,元素不可為空

HashMap和Hashtable的區別:

相同點:HashMap和Hashtable都是java的集合類,都可以用來存放java對象

不同點:

1.歷史原因:Hashtable是基于陳舊的Dictionary類的,HashMap是java 1.2引進的Map接口的一個現實。

2.同步性:Hashtable是同步的,這個類中的一些方法保證了Hashtable中的對象是線程安全的,而HashMap則是異步的,因此HashMap中的對象并不是線程安全的,因為同步的要求會影響執行的效率,所以如果你不需要線程安全的結合那么使用HashMap是一個很好的選擇,這樣可以避免由于同步帶來的不必要的性能開銷,從而提高效率,我們一般所編寫的程序都是異步的,但如果是服務器端的代碼除外。

3.值:HashMap可以讓你將空值作為一個表的條目的key或value,Hashtable是不能放入空值(null)的

ArrayList和Vector的區別:

相同點:ArrayList與Vector都是java的集合類,都是用來存放java對象

不同點:

1.同步性:Vector是同步的,這個類的一些方法保證了Vector中的對象的線程安全的,而ArrayList則是異步的,因此ArrayList中的對象并不 是線程安全的,因為同步要求會影響執行的效率,所以你不需要線程安全的集合那么使用ArrayList是一個很好的選擇,這樣可以避免由于同步帶來的不必 要的性能開銷。

2.數據增長:從內部實現的機制來講,ArrayList和Vector都是使用數組(Array)來控制集合中的對象,當你向兩種類型中增加元素的時候,如果元素的數目超過了內部數組目前的長度他們都需要擴展內部數組的長度,Vector缺省情況下自動增長原來一倍的數組長度,ArrayList是原來的50%,所以最后你獲得的這個集合所占的空間總是比你實際需要的要大,所以如果你要在集合中保存大量的數據,那么使用Vector有一些優勢,因為你可以通過設置集合的初始大小來避免不必要的資源開銷。

總結:

1)如果要求線程安全,使用Vector,Hashtable

2)如果不要求線程安全,使用ArrayList,LinkedList,HashMap

3)如果要求鍵值對,則使用HashMap,Hashtable

4)如果數據量很大,又要求線程安全考慮Vector

arraylist和linkedlist聯系與區別

1.ArrayList是實現了基于動態數組的數據結構,LinkedList基于鏈表的數據結構。

2.對于隨機訪問get和set,ArrayList覺得優于LinkedList,因為LinkedList要移動指針。

3.對于新增和刪除操作add和remove,LinedList比較占優勢,因為ArrayList要移動數據。 這一點要看實際情況的。若只對單條數據插入或刪除,ArrayList的速度反而優于LinkedList。但若是批量隨機的插入刪除數據,LinkedList的速度大大優于ArrayList. 因為ArrayList每插入一條數據,要移動插入點及之后的所有數據。

HashMap與TreeMap聯系與區別

1、 HashMap通過hashcode對其內容進行快速查找,而TreeMap中所有的元素都保持著某種固定的順序,如果你需要得到一個有序的結果你就應該使用TreeMap(HashMap中元素的排列順序是不固定的)。

2、在Map 中插入、刪除和定位元素,HashMap是最好的選擇。但如果您要按自然順序或自定義順序遍歷鍵,那么TreeMap會更好。使用HashMap要求添加的鍵類明確定義了hashCode()和 equals()的實現。

兩個map中的元素一樣,但順序不一樣,導致hashCode()不一樣。

同樣做測試:

在HashMap中,同樣的值的map,順序不同,equals時,false;

而在treeMap中,同樣的值的map,順序不同,equals時,true,說明,treeMap在equals()時是整理了順序了的。

總結

以上是生活随笔為你收集整理的java集合是wftc_Java集合的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。