ArrayList 詳解
底層是數(shù)組,查詢快增刪慢澜共,線程不安全,效率高锥腻。初始化長度10
說一下ArrayList底層實現(xiàn)方式嗦董?
①ArrayList通過數(shù)組實現(xiàn),一旦我們實例化ArrayList無參數(shù)構(gòu)造函數(shù)默認(rèn)為數(shù)組初始化長度為10
②add方法底層實現(xiàn)如果增加的元素個數(shù)超過了10個瘦黑,那么ArrayList底層會新生成一個數(shù)組京革,長度為原數(shù)組的1.5倍+1,然后將原數(shù)組的內(nèi)容復(fù)制到新數(shù)組當(dāng)中幸斥,并且后續(xù)增加的內(nèi)容都會放到新數(shù)組當(dāng)中匹摇。當(dāng)新數(shù)組無法容納增加的元素時,重復(fù)該過程甲葬。是一旦數(shù)組超出長度廊勃,就開始擴容數(shù)組。擴容數(shù)組調(diào)用的方法 Arrays.copyOf(objArr, objArr.length + 1);
結(jié)構(gòu)圖
https://blog.csdn.net/u013309870/article/details/72519272
public class ArrayList<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, Serializable
由上可知ArrayList繼承AbstractList 并且實現(xiàn)了List和RandomAccess经窖,Cloneable, Serializable接口坡垫。
ArrayList的方法使用和源碼解析
①構(gòu)造方法
//1-----------------------
public ArrayList() {
this(10);
//調(diào)用ArrayList(10) 默認(rèn)初始化一個大小為10的object數(shù)組梭灿。
}
//2-------------------------
public ArrayList(int initialCapacity) {
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
//如果用戶初始化大小小于0拋異常,否則新建一個用戶初始值大小的object數(shù)組冰悠。
this.elementData = new Object[initialCapacity];
}
//3--------------------------
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
size = elementData.length;
// 當(dāng)c.toArray返回的不是object類型的數(shù)組時堡妒,進行下面轉(zhuǎn)化。
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
}
由上面三種構(gòu)造方法可知屿脐,默認(rèn)情況下使用ArrayList會生成一個大小為10的Object類型的數(shù)組涕蚤。也可以調(diào)用ArrayList(int initialCapacity) 來初始化Object數(shù)組的大小。并且用戶可以往ArrayList中傳入一個容器只要這個容器是Collection類型的的诵。調(diào)用ArrayList(Collection<? extends E> c)接口的時候會將容器數(shù)組化處理并將這個數(shù)組值賦給Object數(shù)組万栅。
實例:
public static void main(String[] args) {
ArrayList<Integer> list_2=new ArrayList<Integer>(20);
//list_2中添加元素
for(int i=0;i<10;i++)
list_2.add(i);
ArrayList<Integer> list_3=new ArrayList<Integer>(list_2);
//輸出list_2中元素
for(Integer a:list_2)
System.out.print(a+" ");
//輸出list_3中元素
for(Integer a:list_3)
System.out.print(a+" ");
}
//輸出
/*
list_2 : 0 1 2 3 4 5 6 7 8 9
-----------------------
list_3 : 0 1 2 3 4 5 6 7 8 9
*/
②indexOf(Object o)方法
功能:查找某個元素在ArrayList中第一次出現(xiàn)的位置。
public int indexOf(Object o) {
//ArrayList中的元素可以為null西疤,如果為null返回null的下標(biāo)
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
//如果沒有找到對應(yīng)的元素返回-1烦粒。
return -1;
}
對于indexof方法做幾點說明:ArrayList中可以存放null元素,indexof是返回elementData數(shù)組中值相同的首個元素的下標(biāo)代赁,indexof中比較方法是equals而equals是比較元素的值扰她,因此必須對null單獨查找。如果未找到該元素則返回-1 芭碍。
public static void main(String[] args) {
ArrayList<Integer> list=new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(null);
list.add(2);
list.add(3);
System.out.println("null: "+list.indexOf(null));
System.out.println("-------------------------");
System.out.println("2: "+list.indexOf(2));
System.out.println("-------------------------");
System.out.println("4: "+list.indexOf(4));
}
//輸出
/*
null: 2
-------------------------
2: 1
-------------------------
4: -1
*/
③lastIndexOf(Object o)方法
功能:查找某個元素在ArrayList中最后出現(xiàn)的位置锁孟。
public int lastIndexOf(Object o) {
if (o == null) {
//如果o為null從后往前找到第一個為null的下標(biāo)
for (int i = size-1; i >= 0; i--)
if (elementData[i]==null)
return i;
} else {
//從后往前找到第一個值為o的下標(biāo)
for (int i = size-1; i >= 0; i--)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
上面代碼做幾點說明:lastIndexOf(Object o)在ArrayList中從后往前找到第一個跟要查找值相同的元素的下標(biāo)姐浮,因為是按值查找所以對于 null 要單獨查找麸折。如果未找到則返回-1垫言;
④get(int index)方法
功能:返回ArrayList中指定下標(biāo)為index的元素。
//檢查index的值是否大于ArrayList的大小
rangeCheck(index);
//返回index下標(biāo)的元素
return elementData(index);
}
E elementData(int index) {
return (E) elementData[index];
}
//這里值檢查index >= size的情況瞻讽,因為index<0時會自動拋出異常鸳吸,所以并未檢查index<0的情況。
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}```
對上面代碼做幾點說明:上面代碼中只檢查了index>=size的情況速勇,在index<0的情況下也會拋出異常晌砾,只是這個異常是由系統(tǒng)拋出的。index>=size要檢查的原因是有可能數(shù)組的大小大于index烦磁,然而有效里面的元素<index這時不拋異常就會返回?zé)o效值养匈。舉個例子ArrayList的初始化大小為10,現(xiàn)在往里面放5個元素个初,如果index>=5時乖寒,應(yīng)該要拋出異常,而不是返回 null院溺。因為null 是可以主動放在ArrayList中的。
###⑤set(int index, E element)方法
功能:將element放到ArrayList下標(biāo)為index的位置磅轻,如果index<0或index>=size 拋異常珍逸,set(int index, E element)只能覆蓋ArrayList中原來的元素逐虚,返回值為被覆蓋的元素。
```//1
public E set(int index, E element) {
//檢查index是否小于size谆膳,如果不是拋異常
rangeCheck(index);
E oldValue = elementData(index);
elementData[index] = element;
//覆蓋ArrayList中index上的元素叭爱。
return oldValue;
//返回被覆蓋的元素。
}
//2
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
⑥add(E e)方法
功能:往ArrayList中添加元素漱病。
public boolean add(E e) {
ensureCapacityInternal(size + 1); // 加入元素前檢查數(shù)組的容量是否足夠
elementData[size++] = e;
return true;
}
//2-----------------------
private void ensureCapacityInternal(int minCapacity) {
modCount++;
// 如果添加元素后大于當(dāng)前數(shù)組的長度买雾,則進行擴容
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
//3-----------------------
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
//將數(shù)組的長度增加原來數(shù)組的一半。
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//如果擴充一半后仍然不夠杨帽,則 newCapacity = minCapacity;minCapacity實際元素的個數(shù)漓穿。
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
//數(shù)組最大位2^32
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
add方法比較復(fù)雜,涉及到擴充數(shù)組容量的問題注盈。其中要弄清楚size和elementData.length的區(qū)別晃危,size指的是數(shù)組中存放元素的個數(shù),elementData.length表示數(shù)組的長度老客,當(dāng)new一個ArrayList系統(tǒng)默認(rèn)產(chǎn)生一個長度為10的elementData數(shù)組僚饭,elementData.length=10,但是由于elementData中還未放任何元素所有size=0胧砰。如果加入元素后數(shù)組大小不夠會先進行擴容鳍鸵,每次擴容都將數(shù)組大小增大一半比如數(shù)組大小為10一次擴容后的大小為10+5=10;ArrayList的最大長度為 2^32 .
⑦add(int index, E element)方法
功能:往ArrayList指定index上添加元素,添加元素后ArrayList的大小增1尉间。index及以后的元素都會向后移一位偿乖。
public void add(int index, E element) {
rangeCheckForAdd(index);
//檢查index的值是否在0到size之間,可以為size乌妒。
ensureCapacityInternal(size + 1); // 看elementData的長度是否足夠汹想,不夠擴容
//將elementData從index開始后面的元素往后移一位。
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
//2-------------------------
private void rangeCheckForAdd(int index) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
//3-------------------------
private void ensureCapacityInternal(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}```
add(int index, E element)往指定index中加入元素撤蚊,加入元素之前先檢查數(shù)組的大小古掏,如果小了在原來基礎(chǔ)上增大一半,將ArrayList只能怪index及以后的元素往后移一位侦啸,將element放到index位置槽唾。
###⑧remove(int index)方法
功能:刪除ArrayList指定位置的元素。
public E remove(int index) {
rangeCheck(index);
//如果index>=size拋出異常
modCount++;
E oldValue = elementData(index);
//獲取刪除元素的值
int numMoved = size - index - 1;
//將index后面所有的元素往前移一位光涂。
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // Let gc do its work
//返回要刪除的原數(shù)庞萍。
return oldValue;
}```
⑨remove(Object o)方法
功能:刪除ArrayList中值為o的元素
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
ArrayList和LinkedList的大致區(qū)別如下:
1.ArrayList是實現(xiàn)了基于動態(tài)數(shù)組的數(shù)據(jù)結(jié)構(gòu),LinkedList基于鏈表的數(shù)據(jù)結(jié)構(gòu)忘闻。
2.對于隨機訪問 钝计,ArrayList覺得優(yōu)于LinkedList,因為LinkedList要移動指針。
3.對于新增和刪除操作add和remove私恬,LinedList比較占優(yōu)勢债沮,因為ArrayList要移動數(shù)據(jù)。
說一下LinkedList底層實現(xiàn)方式本鸣?
LinkedList底層的數(shù)據(jù)結(jié)構(gòu)是基于雙向循環(huán)鏈表的疫衩,且頭結(jié)點中不存放數(shù)據(jù),如下:
雙向鏈表數(shù)據(jù)結(jié)構(gòu):稱之為節(jié)點,節(jié)點實例保存業(yè)務(wù)數(shù)據(jù)荣德,前一個節(jié)點的位置信息和后一個節(jié)點位置信息闷煤,如下圖所示:
初始化長度
1.StringBuffer和StringBuilder初始化默認(rèn)大小為16個字符
2.HashMap初始化默認(rèn)大小16,自增為2n.
3.HashTable默認(rèn)初始值為11涮瞻,加載因子為0.75鲤拿,自增為2n+1
4.ArrayList初始化默認(rèn)值為10,自增為1.5n
5.Vector初始化默認(rèn)值為10饲宛,自增為2n
ArrayList 和 Vector 的區(qū)別
這兩個類都實現(xiàn)了 List 接口(List 接口繼承了Collection 接口),他們都是有序集合,即存儲在這兩個集合中的元素的位置都是有順序的,相當(dāng)于一種動態(tài)的數(shù)組,我們以后可以按位置索引號取出某個元素,并且其中的數(shù)據(jù)是允許重復(fù)的,
ArrayList 與 Vector 的區(qū)別,這主要包括兩個方面:.
(1)同步性:
Vector 是線程安全的,
ArrayList 是線程序不安全的皆愉。
單線程使用arraylist,多線程使用vector
(2)數(shù)據(jù)增長:
ArrayList初始化默認(rèn)值為10艇抠,自增為1.5n
Vector初始化默認(rèn)值為10幕庐,自增為2n
List 和Set、Map 區(qū)別?
Java中的集合包括三大類家淤,它們是Set异剥、List和Map,它們都處于java.util包中絮重,Set冤寿、List和Map都是接口,它們有各自的實現(xiàn)類青伤。Set的實現(xiàn)類主要有HashSet和TreeSet督怜,List的實現(xiàn)類主要有ArrayList,Map的實現(xiàn)類主要有HashMap和TreeMap狠角。
Set中的對象不按特定方式排序号杠,并且沒有重復(fù)對象。但它的有些實現(xiàn)類能對集合中的對象按特定方式排序丰歌,例如TreeSet類姨蟋,它可以按照默認(rèn)排序,也可以通過實現(xiàn)java.util.Comparator<Type>接口來自定義排序方式立帖。
List中的對象按照索引位置排序眼溶,可以有重復(fù)對象,允許按照對象在集合中的索引位置檢索對象晓勇,如通過list.get(i)方式來獲得List集合中的元素堂飞。
Map中的每一個元素包含一個鍵對象和值對象灌旧,它們成對出現(xiàn)。鍵對象不能重復(fù)酝静,值對象可以重復(fù)节榜。
說一下HashMap底層實現(xiàn)方式羡玛?
HashMap是由數(shù)組+鏈表組成
put方法底層實現(xiàn):
通過key的hash值%Entry[].length得到該存儲的下標(biāo)位置别智,如果多個key的hash值%Entry[].length值相同話就就會存儲到該鏈表的后面。
Collection 和 Collections 的區(qū)別稼稿。
Collection是集合類的上級接口薄榛,繼承于它的接口主要有Set和List。 Collections是針對集合類的一個幫助類让歼,它提供了一系列靜態(tài)方法實現(xiàn)了對各種集合的排序敞恋,搜索和線程安全等操作。
List谋右、Map硬猫、Set 三個接口,存取元素時,各有什么特點?
list:存儲: 有序的 可重復(fù)的
訪問:可以for循環(huán),foreach循環(huán),iterator迭代器改执。set:存儲:無序的 不重復(fù)的
訪問:可以foreach循環(huán)啸蜜,iterator迭代器 迭代map:存儲:存儲的是一對一對的映射 ”key=value“,key值 是無序辈挂,不重復(fù)的衬横。value值可重復(fù)
訪問:可以map中key值轉(zhuǎn)為為set存儲,然后迭代這個set终蒂,用map.get(key)獲取value
,也可以轉(zhuǎn)換為entry對象用迭代器迭代
HashMap 和 Hashtable 的區(qū)別
- hashmap:線程不安全,允許有null的鍵和值,效率高.HashMap是Hashtable的輕量級實現(xiàn)
有containsvalue和containsKey方法,HashMap 是Java1.2 引進的Map interface 的一個實現(xiàn) -
hashtable:線程安全不允許有null的鍵和值,效率低.方法是Synchronize的.有contains方法 蜂林、Hashtable 繼承于Dictionary 類.
HashMap,HashTable拇泣,ConcurrentHashMap的區(qū)別噪叙。
HashMap簡介
HashMap 是一個散列表,它存儲的內(nèi)容是鍵值對(key-value)映射霉翔。
HashMap 繼承于AbstractMap睁蕾,實現(xiàn)了Map、Cloneable早龟、java.io.Serializable接口惫霸。
HashMap 的實現(xiàn)不是同步的,這意味著它不是線程安全的葱弟。它的key壹店、value都可以為null。此外芝加,HashMap中的映射不是有序的硅卢。
HashMap 的實例有兩個參數(shù)影響其性能:“初始容量10” 和 “加載因子0.75”射窒。容量 是哈希表中桶的數(shù)量,初始容量 只是哈希表在創(chuàng)建時的容量将塑。加載因子 是哈希表在其容量自動增加之前可以達到多滿的一種尺度脉顿。當(dāng)哈希表中的條目數(shù)超出了加載因子與當(dāng)前容量的乘積時,則要對該哈希表進行 rehash 操作(即重建內(nèi)部數(shù)據(jù)結(jié)構(gòu))点寥,從而哈希表將具有大約兩倍的桶數(shù)艾疟。
通常,默認(rèn)加載因子是 0.75, 這是在時間和空間成本上尋求一種折衷敢辩。加載因子過高雖然減少了空間開銷蔽莱,但同時也增加了查詢成本(在大多數(shù) HashMap 類的操作中,包括 get 和 put 操作戚长,都反映了這一點)盗冷。在設(shè)置初始容量時應(yīng)該考慮到映射中所需的條目數(shù)及其加載因子,以便最大限度地減少 rehash 操作次數(shù)同廉。如果初始容量大于最大條目數(shù)除以加載因子仪糖,則不會發(fā)生 rehash 操作。
去掉一個 Vector 集合中重復(fù)的元素
通過Vector.contains()方法判斷是否包含該元素迫肖,如果沒有包含就添加到新的集合當(dāng)中锅劝,適用于數(shù)據(jù)較小的情況下。
Set 里的元素是不能重復(fù)的.
set里的元素是不能重復(fù)的咒程,用iterator()方法來區(qū)分重復(fù)與否鸠天。
HashMap的工作原理
HashMap基于hashing原理,我們通過put()和get()方法儲存和獲取對象帐姻。當(dāng)我們將鍵值對傳遞給put()方法時稠集,它調(diào)用鍵對象的hashCode()方法來計算hashcode,讓后找到bucket位置來儲存值對象饥瓷。當(dāng)獲取對象時剥纷,通過鍵對象的equals()方法找到正確的鍵值對,然后返回值對象呢铆。HashMap使用鏈表來解決碰撞問題晦鞋,當(dāng)發(fā)生碰撞了,對象將會儲存在鏈表的下一個節(jié)點中悠垛。 HashMap在每個鏈表節(jié)點中儲存鍵值對對象。
當(dāng)兩個不同的鍵對象的hashcode相同時會發(fā)生什么确买? 它們會儲存在同一個bucket位置的鏈表中。鍵對象的equals()方法用來找到鍵值對湾趾。
因為HashMap的好處非常多芭商,我曾經(jīng)在電子商務(wù)的應(yīng)用中使用HashMap作為緩存铛楣。因為金融領(lǐng)域非常多的運用Java,也出于性能的考慮簸州,我們會經(jīng)常用到HashMap和ConcurrentHashMap衷敌。你可以查看更多的關(guān)于HashMap的文章:
說一下什么是哈希表
那么我們能不能綜合兩者的特性,做出一種尋址容易缴罗,插入刪除也容易的數(shù)據(jù)結(jié)構(gòu)祭埂?答案是肯定的,這就是我們要提起的哈希表舌界。哈希表((Hash table)既滿足了數(shù)據(jù)的查找方便,同時不占用太多的內(nèi)容空間泰演,使用也十分方便呻拌。
哈希表有多種不同的實現(xiàn)方法,我接下來解釋的是最常用的一種方法—— 拉鏈法睦焕,我們可以理解為“鏈表的數(shù)組” 藐握,如圖:
請說下Iterator的作用
迭代器可以實現(xiàn)Collection接口的方法,可以一個一個地獲取集合中的元素
在遍歷集合時 可判斷是否有下一個元素
說下ArrayList和LinkedList的區(qū)別和聯(lián)系垃喊,并說明什么情況下用它們
區(qū)別:ArrayList用于對象的隨機訪問速度快,沒有順序
LinkedList實現(xiàn)機制是鏈表式的,和順序有關(guān),速度比ArrayList慢
聯(lián)系:ArrayList和LinkedList都是List接口的實現(xiàn)類
當(dāng)要快速獲取一個值時,用ArrayList,用于順序插入操作時,用LinkedList.
說下List猾普,Set,Map三種集合各有什么特征
List集合中的元素可以重復(fù),
Set集合中的元素不可以重復(fù)
Map集合用鍵-值映射存放對象,Map容器中的鍵對象不能重復(fù),值對象可以重復(fù)
HashSet和TreeSet有什么區(qū)別本谜,什么時候用它們
區(qū)別:HashSet中的元素不能重復(fù),沒有順序
TreeSet中的元素不能重復(fù),但有順序
排序使用TreeSet初家,不排序使用HashSet,效率比排序快乌助。
HaspMap擴容是怎樣擴容的
HashMap中的變量
首先要了解HashMap的擴容過程溜在,我們就得了解一些HashMap中的變量:
Node<K,V>:鏈表節(jié)點,包含了key他托、value掖肋、hash、next指針?biāo)膫€元素
table:Node<K,V>類型的數(shù)組上祈,里面的元素是鏈表培遵,用于存放HashMap元素的實體
size:記錄了放入HashMap的元素個數(shù)
loadFactor:負載因子
threshold:閾值浙芙,決定了HashMap何時擴容,以及擴容后的大小籽腕,一般等于table大小乘以loadFactor
- 定義初始容量大形撕簟(table數(shù)組的大小,缺省值為16)皇耗,定義負載因子(缺省值為0.75)的形式
HaspMap擴容是怎樣擴容的南窗,為什么都是2的N次冪的大小。
- 定義初始容量大欣陕ァ(table數(shù)組的大小万伤,缺省值為16),定義負載因子(缺省值為0.75)的形式
有幾個重要的常量:
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;//默認(rèn)的桶數(shù)組大小
static final int MAXIMUM_CAPACITY = 1 << 30;//極限值(超過這個值就將threshold修改為Integer.MAX_VALUE(此時桶大小已經(jīng)是2的31次方了)呜袁,表明不進行擴容了)
static final float DEFAULT_LOAD_FACTOR = 0.75f;//負載因子(請閱讀下面體會這個值的用處)
HashMap與LinkedHashMap,和TreeMap的區(qū)別敌买。
共同點:HashMap,LinkedHashMap,TreeMap都屬于Map的實現(xiàn)類.
不同點: 1.HashMap里面存入的鍵值對在取出的時候是隨機的,
2.TreeMap取出來的是排序后的鍵值對阶界。但如果您要按自然順序或自定義順序遍歷鍵膘融,那么TreeMap會更好。
3.LinkedHashMap 是HashMap的一個子類春畔,如果需要輸出的順序和輸入的相同,那么用LinkedHashMap可以實現(xiàn).
什么是for each循環(huán)律姨,它可以循環(huán)那些數(shù)據(jù)類型
也可以叫增強型循環(huán)线召,通過對象拿到集合里的值缓淹,因為擴展性比較強讯壶,建議多使用伏蚊,可以用來循環(huán)集合和數(shù)組
什么是泛型躏吊,怎么使用的,有什么好處胜卤?
定義一個集合時葛躏,可以知道里面定義的是什么類型
使用:在集合類型后面加< 數(shù)據(jù)類型 >
- 使用泛型后,從集合中取得元素后就不用再用強轉(zhuǎn)
比較下集合和數(shù)組的優(yōu)缺點
- 集合:是多個對象的容器,可以將不同數(shù)據(jù)類型的多個對象組織在一起
- 數(shù)組:是有相同數(shù)據(jù)類型的數(shù)據(jù)集合,數(shù)組是很多語言都支持的底層數(shù)據(jù)結(jié)構(gòu),性能上是最高的
在List里面怎么去掉重復(fù)的數(shù)舰攒?
通過把List里面的數(shù)據(jù)放入HashSet可以去除重復(fù)
HashMap和ArrayList是不是都是線程不安全的摩窃?
ArrayList是線程不安全的偶芍;
HashMap是線程不安全的;
還有我們常見的一些JAVA集合都是線程不安全,這樣做是為了提高性能在JDK5以后提供了線程安全的并發(fā)包java.util.concurrent并發(fā)包,譬如里面的類CopyOnWriteArrayList,
CopyOnWriteArraySet,ConcurrentHashMap等
ArrayList集合加入1萬條數(shù)據(jù)椎麦,應(yīng)該怎么提高效率
因為ArrayList的底層是數(shù)組實現(xiàn),并且數(shù)組的默認(rèn)值是10,如果插入10000條要不斷的擴容,耗費時間,所以我們調(diào)用ArrayList的指定容量的構(gòu)造器方法ArrayList(int size) 就可以實現(xiàn)不擴容,就提高了性能