1.ArrayList详解及扩容源码分析
2.面试题:ArrayList扩容时扩容多少?
3.List LinkedList HashSet HashMap底层原理剖析
4.å¦ä½èªå·±å®ç°ä¸ä¸ªç®åçArrayList
5.arraylist如何实现序列化?码原
6.arraylist为ä»ä¹çº¿ç¨ä¸å®å
¨
ArrayList详解及扩容源码分析
在集合框架中,ArrayList作为普通类实现List接口,码原如下图所示。码原 它实现了RandomAccess接口,码原表明支持随机访问;Cloneable接口,码原表明可以实现克隆;Serializable接口,码原中国梦源码表明支持序列化。码原 与其他类不同,码原如Vector,码原ArrayList在单线程环境下的码原线程安全性较差,但适用于多线程环境下的码原Vector或CopyOnWriteArrayList。 ArrayList底层基于连续的码原空间实现,为动态可扩展的码原顺序表。一、码原构造方法解析
使用ArrayList(Collection c)构造方法时,码原传入类型必须为E或其子类。二、扩容分析
不带参数的构造方法初始容量为,此时底层数组为空,即`DEFAULT_CAPACITY_EMPTY_ELEMENTDATA`长度为0。 元素添加时,默认插入数组末尾,调用`ensureCapacityInternal(size + 1)`增加容量。dnf端口辅助源码 若当前容量无法满足增加需求,计算新的容量以达到所需规模,确保添加元素成功并避免频繁扩容。三、常用方法
通过List.subList(int fromIndex, int toIndex)方法获取子列表,修改原列表元素亦会改变此子列表。四、遍历方式
ArrayList提供for循环、foreach循环、迭代器三种遍历方法。五、缺陷与替代方案
ArrayList基于数组实现,插入或删除元素导致频繁元素移动,时间复杂度高。在需要任意位置频繁操作的场景下,性能不佳。 因此,在Java集合中引入了更适合频繁插入和删除操作的LinkedList类。 版权声明:本文内容基于阿里云实名注册用户的贡献,遵循相关协议规定,包括用户服务协议和知识产权保护指引。发现抄袭内容,eclipse class源码乱码可通过侵权投诉表单举报,确保社区内容健康、合规。面试题:ArrayList扩容时扩容多少?
大家好,我是你们的小米!今天要和大家一起来探讨一个在Java面试中经常被问到的问题:“ArrayList扩容时扩容多少?”相信很多小伙伴都在面试中遇到过这个问题,那么接下来,我就为大家详细解析一下这个问题,希望能够帮助大家在面试中游刃有余!
了解ArrrayList的内部实现
在深入解析扩容策略之前,我们首先要了解一下ArrayList的内部实现原理。ArrayList是Java集合框架中的一个动态数组,它可以根据需要动态地增加或减少元素。ArrayList的底层是通过数组实现的,当数组容量不足以存放新增的元素时,就需要进行扩容操作。
扩容策略简介
ArrayList在扩容时,并不是每次新增一个元素就扩容一次,这样效率会很低。相反,它采取了一种“倍增”策略,即当数组容量不够用时,epub在线阅读源码它会将当前容量翻倍。这样做的好处是,在一次扩容操作中,可以一次性扩充一大块内存,减少了频繁扩容带来的性能损耗。
源码分析
ArrayList的扩容逻辑实际上是由ensureCapacityInternal方法来完成的。我们一起来看一下这段源码:
从上面的代码中,我们可以看到,在grow方法中,新的容量(newCapacity)是通过将旧容量(oldCapacity)右移一位(即除以2),然后再加上旧容量得到的。这样就实现了容量的翻倍扩容策略。
理解扩容的触发条件
在源码分析的基础上,我们来总结一下ArrayList扩容的触发条件:
需要注意的是,虽然数组会根据倍增策略进行扩容,但也并不是无限制地扩容下去的。在源码中,有一个MAX_ARRAY_SIZE的限制,如果计算得到的新容量超过了这个值,就会进行特殊处理。
END
通过对ArrayList扩容策略的源码分析和解释,我们可以得出ArrayList在扩容时采用了倍增策略,github spring源码下载每次扩容都会将当前容量翻倍,从而有效地减少了频繁扩容带来的性能损耗。同时,也要注意到MAX_ARRAY_SIZE的限制,防止无限制地扩容。掌握了这些知识,相信在面试中回答关于ArrayList扩容策略的问题时,大家已经游刃有余了!
List LinkedList HashSet HashMap底层原理剖析
ArrayList底层数据结构采用数组。数组在Java中连续存储,因此查询速度快,时间复杂度为O(1),插入数据时可能会慢,特别是需要移动位置时,时间复杂度为O(N),但末尾插入时时间复杂度为O(1)。数组需要固定长度,ArrayList默认长度为,最大长度为Integer.MAX_VALUE。在添加元素时,如果数组长度不足,则会进行扩容。JDK采用复制扩容法,通过增加数组容量来提升性能。若数组较大且知道所需存储数据量,可设置数组长度,或者指定最小长度。例如,设置最小长度时,扩容长度变为原有容量的1.5倍,从增加到。
LinkedList底层采用双向列表结构。链表存储为物理独立存储,因此插入操作的时间复杂度为O(1),且无需扩容,也不涉及位置挪移。然而,查询操作的时间复杂度为O(N)。LinkedList的add和remove方法中,add默认添加到列表末尾,无需移动元素,相对更高效。而remove方法默认移除第一个元素,移除指定元素时则需要遍历查找,但与ArrayList相比,无需执行位置挪移。
HashSet底层基于HashMap。HashMap在Java 1.7版本之前采用数组和链表结构,自1.8版本起,则采用数组、链表与红黑树的组合结构。在Java 1.7之前,链表使用头插法,但在高并发环境下可能会导致链表死循环。从Java 1.8开始,链表采用尾插法。在创建HashSet时,通常会设置一个默认的负载因子(默认值为0.),当数组的使用率达到总长度的%时,会进行数组扩容。HashMap的put方法和get方法的源码流程及详细逻辑可能较为复杂,涉及哈希算法、负载因子、扩容机制等核心概念。
å¦ä½èªå·±å®ç°ä¸ä¸ªç®åçArrayList
ArrayListæ¯Javaéåæ¡æ¶ä¸ä¸ä¸ªç»å ¸çå®ç°ç±»ãä»æ¯èµ·å¸¸ç¨çæ°ç»èè¨ï¼ææ¾çä¼ç¹å¨äºï¼å¯ä»¥éæçæ·»å åå é¤å ç´ èä¸éèèæ°ç»ç大å°ãå®ç°ä¸ä¸ªç®åçArrayListï¼å®ç°çè¿ç¨ï¼
å®ç°çArrayList主è¦çåè½å¦ä¸ï¼
é»è®¤æé å¨åä¸ä¸ªåæ°çæåæé å¨
addæ¹æ³
getæ¹æ³
indexOfæ¹æ³
containsæ¹æ³
sizeæ¹æ³
isEmptyæ¹æ³
removeæ¹æ³
è¿ä¸ªç®åçArrayListç±» åå为SimpleArrayListï¼å ¨é¨ç代ç æ¥çSimpleArrayList代ç
æé å¨
æºç ArrayListä¸å ±æä¸ä¸ªæé å¨ï¼ä¸ä¸ªæ åæé å¨ï¼ä¸ä¸ªåæ°ä¸ºintåæåæé å¨ï¼ä¸ä¸ªåæ°ä¸ºCollectionåçæåæé å¨ãåæ°ä¸ºCollectionåçæé å¨ç¨æ¥å®ç°å°å ¶ä»ç»§æ¿Collectionç±»ç容å¨ç±»è½¬æ¢æArrayListãSimpleArrayListç±»å 为è¿æ²¡ææå¨å®ç°å ¶ä»ç容å¨ç±»ï¼æ以å®ç°çæé æ¹æ³åªæ2个ã代ç å¦ä¸ï¼
public SimpleArrayList(){ this(DEFAULT_CAPACITY);} public SimpleArrayList(int size){ if (size < 0){ throw new IllegalArgumentException("é»è®¤ç大å°" + size);
}else{
elementData = new Object[size];
}
}
æ åæé å¨ä¸ç DEFAULT_CAPACITYæ¯å®ä¹çç§æåéï¼é»è®¤å¼æ¯ï¼ç¨æ¥å建ä¸ä¸ªå¤§å°ä¸ºçæ°ç»ãæåæé å¨ä¸ï¼intåæ°æ¯ç¨æ¥çæä¸ä¸ªæå®å¤§å°çObjectæ°ç»ãå°å建好çæ°ç»ä¼ ç»elementDataãelementDataæ¯çæ£çç¨æ¥åå¨å ç´ çæ°ç»ãaddæ¹æ³
add æ¹æ³ç¨æ¥å¾å®¹å¨ä¸æ·»å å ç´ ï¼addæ¹æ³æ两个éè½½æ¹æ³ï¼ä¸ä¸ªæ¯add(E e),å¦ä¸ä¸ªæ¯add(int index, E e)ãaddæ¬èº«å¾ç®åï¼ä½æ¯è¦å¤çå¨ææ°ç»ï¼å³æ°ç»å¤§å°ä¸æ»¡è¶³çæ¶åï¼æ©å¤§æ°ç»çå åãå ·ä½ç代ç å¦ä¸ï¼
public void add(E e){isCapacityEnough(size + 1);
elementData[size++] = e;
}
æ¹æ³isCapacityEnoughå°±æ¯æ¥å¤ææ¯å¦éè¦æ©å®¹ï¼ä¼ å ¥çåæ°å°±æ¯æå°çæ©å®¹ç©ºé´ãå 为addä¸ä¸ªå ç´ ï¼æ以æå°çæ©å®¹ç©ºé´ï¼å³æ°çé¿åº¦æ¯ææå ç´ + 1ãè¿éçsizeå°±æ¯çæ£çå ç´ ä¸ªæ°ã private void isCapacityEnough(int size){ if (size > DEFAULT_CAPACITY){explicitCapacity(size);
} if (size < 0){ throw new OutOfMemoryError();
}
}
å¤ææ©å®¹çæ¹æ³ä¹å¾ç®åï¼å¤æéè¦æ©å®¹ç空é´æ¯ä¸æ¯æ¯é»è®¤ç空é´å¤§ãå¦æéè¦ç空é´æ¯é»è®¤ç空é´å¤§ï¼å°±è°ç¨explicitCapacityè¿è¡æ©å®¹ãè¿éæ个sizeå°äº0çå¤æï¼åºç°sizeå°äº0主è¦æ¯å 为å½sizeè¶ è¿Integer.MAX_VALUEå°±ä¼åæè´æ°ã private final static int MAX_ARRAY_LENGTH = Integer.MAX_VALUE - 8; private void explicitCapacity(int capacity){ int newLength = elementData.length * 2; if (newLength - capacity < 0){newLength = capacity;
} if (newLength > (MAX_ARRAY_LENGTH)){
newLength = (capacity > MAX_ARRAY_LENGTH ? Integer.MAX_VALUE : MAX_ARRAY_LENGTH);
}
elementData = Arrays.copyOf(elementData, newLength);
}
ä¸é¢ç代ç æ¯æ©å®¹ç代ç ï¼é¦å ï¼å®ä¹ä¸ä¸ªæ°ç»æ大ç容éç常é为æ大å¼ï¼è¿ä¸ªå¼æç §å®æ¹çæºç ä¸ç解éæ¯è¦æäºVMä¿çäºæ°ç»ç头é¨ä¿¡æ¯å¨æ°ç»ä¸ï¼å æ¤å®é åæ¾æ°æ®ç大å°å°±æ¯æ´æ°çæå¤§å¼ - 8ç¶å设å®ä¸ä¸ªè¦æ©å®¹çæ°ç»ç大å°ï¼è½ç¶ä¸é¢è¯´äºæä¸ä¸ªæ©å®¹ç©ºé´çå¼ size + 1 ï¼è¿ä¸ªæ¯å®é æ们æå°éè¦æ©å®¹ç大å°ãä½ä¸ºäºç»§ç»å¢å å ç´ ï¼èä¸é¢ç¹çæ©å®¹ï¼å æ¤ä¸æ¬¡æ§çç³è¯·å¤ä¸äºçæ©å®¹ç©ºé´ãè¿énewLength æç®ç³è¯·ä¸º æ°ç»é¿åº¦ç2åï¼ç¶åå»å¤æè¿ä¸ªé¿åº¦æ¯å¦æ»¡è¶³éè¦çæ©å®¹ç©ºé´çå¼ã å³æäºåç»ç两段代ç
if (newLength - capacity < 0){ newLength = capacity;} if (newLength > (MAX_ARRAY_LENGTH)){ newLength = (capacity > MAX_ARRAY_LENGTH ? Integer.MAX_VALUE : MAX_ARRAY_LENGTH);
}
å¦æ2åçé¿åº¦ä»ç¶ä¸æ»¡è¶³ï¼åç³è¯·å°éè¦çæ©å®¹é¿åº¦ãå¨æ们åªå¢å ä¸ä¸ªå ç´ çæ åµä¸ï¼è¿ä¸ªå¤ææ¯æ°¸è¿ä¸ä¼çæçï¼ä½æ¯å¦ææaddAllæ¹æ³ï¼åå¢å çå ç´ å¾å¤ï¼å°±è¦å¯¼è´ä¸æ¬¡ç³è¯·2åçé¿åº¦æ¯ä¸å¤çã第äºä¸ªå¤ææ¯å¤ænewLengthçé¿åº¦å¦æè¶ è¿ä¸é¢å®ä¹çæ°ç»æ大é¿åº¦åå¤æè¦éè¦çæ©å®¹ç©ºé´æ¯å¦å¤§äºæ°ç»æ大é¿åº¦ï¼å¦æ大äºånewLength为 MAX_VALUE ï¼å¦å为 MAX_ARRAY_LENGTHãæåï¼çæ£å®ç°æ°ç»æ©å®¹å°è®¾å®é¿åº¦çæ¹æ³å°±æ²¡ææäºï¼è°ç¨Arrays.copyOf(elementData, newLength)å¾å°ä¸ä¸ªæ©å®¹åçæ°ç»ã
addçå¦ä¸ä¸ªéè½½æ¹æ³ä¹å¾ç®åã
public void add(int index, E e) {//å¤ææ¯ä¸æ¯è¶ç
checkRangeForAdd(index);
//å¤æéä¸éè¦æ©å®¹
isCapacityEnough(size + 1);
//å°indexçå ç´ å以åçå ç´ åå移ä¸ä½
System.arraycopy(elementData,index,elementData,index + 1,size - index);
//å°indexä¸æ çå¼è®¾ä¸ºe
elementData[index] = e; size++;
}
private void checkRangeForAdd(int index){ //è¿éindex = sizeæ¯è¢«å 许çï¼å³æ¯æ头ï¼ä¸é´ï¼å°¾é¨æå ¥
if (index < 0 || index > size){ throw new IndexOutOfBoundsException("æå®çindexè¶ è¿çé");
}
}
è³æ¤ï¼ä¸ä¸ªç®åçaddæ¹æ³å°±å®ç°å®äºãgetæ¹æ³
getæ¹æ³ç¨æ¥å¾å°å®¹å¨ä¸æå®ä¸æ çå ç´ ãæ¹æ³å®ç°æ¯è¾ç®åï¼ç´æ¥è¿åæ°ç»ä¸æå®ä¸æ çå ç´ å³å¯ã
private void checkRange(int index) { if (index >= size || index < 0){throw new IndexOutOfBoundsException("æå®çindexè¶ è¿çé");
}
} public E get(int index){
checkRange(index); return (E)elementData[index];
}
indexOfæ¹æ³indexOfæ¹æ³ç¨æ¥å¾å°æå®å ç´ çä¸æ ãå®ç°èµ·æ¥æ¯è¾ç®åï¼éè¦å¤æä¼ å ¥çå ç´ ï¼ä»£ç å¦ä¸ï¼
public int indexOf(Object o){ if (o != null) { for (int i = 0 ; i < size ; i++){ if (elementData[i].equals(o)){ return i;}
}
}else { for (int i = 0 ; i < size ; i++){ if (elementData[i] == null) { return i;
}
}
} return -1;
}
å¤æä¼ å ¥çå ç´ æ¯å¦ä¸ºnullï¼å¦æ为nullï¼åä¾æ¬¡ä¸nullãå¦æä¸ä¸ºç©ºï¼åç¨equalsä¾æ¬¡æ¯è¾ãå¹é æåå°±è¿åä¸æ ï¼å¹é 失败就è¿å-1ãcontainsæ¹æ³
containsç¨æ¥å¤æ该容å¨ä¸æ¯å¦å å«æå®çå ç´ ãå¨æäºindexOfæ¹æ³çåºç¡ä¸ï¼containsçå®ç°å°±å¾ç®åäºã
public boolean contains(Object o){ return indexOf(o) >= 0;}
sizeæ¹æ³sizeæ¹æ³ç¨æ¥å¾å°å®¹å¨ç±»çå ç´ ä¸ªæ°ï¼å®ç°å¾ç®åï¼ç´æ¥è¿åsizeç大å°å³å¯ã
public int size(){ return size;}
isEmptyæ¹æ³isEmptyæ¹æ³ç¨æ¥å¤æ容å¨æ¯å¦ä¸ºç©ºï¼å¤æsizeæ¹æ³çè¿åå¼æ¯å¦ä¸º0å³å¯ã
public boolean isEmpty(){ return size() == 0;}
removeæ¹æ³removeæ¹æ³æ¯ç¨æ¥å¯¹å®¹å¨ç±»çå ç´ è¿è¡å é¤ï¼ä¸addä¸æ ·ï¼removeæ¹æ³ä¹æ两个éè½½æ¹æ³ï¼åå«æ¯
remove(Object o)åremove(int index)
public E remove(int index) {E value = get(index); int moveSize = size - index - 1; if (moveSize > 0){
System.arraycopy(elementData,index + 1, elementData,index,size - index - 1);
}
elementData[--size] = null; return value;
}
public boolean remove(Object o){ if (contains(o)){
remove(indexOf(o)); return true;
}else { return false;
}
}
第ä¸ä¸ªremoveæ¹æ³æ¯æ ¸å¿æ¹æ³ï¼é¦å å¾å°è¦å é¤çä¸æ å ç´ çå¼ï¼ç¶åå¤æindexåé¢çè¦å移çå ç´ ç个æ°ï¼å¦æ个æ°å¤§äºé¶ï¼åè°ç¨åºæ¹æ³ï¼å°indexåé¢çå ç´ åå移ä¸ä½ãæåelementData[--size] = null;缩åsize大å°ï¼å¹¶å°åæåä¸ä½ç½®ç©ºã第äºä¸ªremoveæ¹æ³ä¸éè¦å第ä¸ä¸ªæ¹æ³ä¸æ ·ï¼éè¦åè¯ä½¿ç¨è è¦å é¤çä¸æ 对åºçå ç´ ï¼åªéè¦å¤ææ¯å¦å é¤æåå³å¯ãå¦æè¦å é¤çå ç´ å¨å表ä¸ï¼åå é¤æåï¼å¦æä¸å¨å失败ãå æ¤è°ç¨containsæ¹æ³å°±å¯ä»¥å¤ææ¯å¦è¦å é¤çå ç´ å¨å表ä¸ãå¨åè°ç¨remove(int index),ä¸å¨åè¿å失败ã
arraylist如何实现序列化?
小彭为您带来关于 ArrayList 如何实现序列化的内容。在实际业务开发中,我们通常直接使用标准库的数据结构,例如 ArrayList。本篇文章将深入解析 ArrayList 的核心实现,包括源码分析、构造方法、添加与扩容、迭代器、序列化过程、clone() 方法、线程安全特性以及 ArrayList 与 Arrays#ArrayList 的区别,并探讨 ArrayList 是否能完全替代数组。
首先,ArrayList 是一个动态数组,底层使用 Object 数组存储元素。其构造方法提供了不同初始容量的选项,懒初始化策略使得在首次添加元素时动态分配内存。
添加元素时,ArrayList 会检查容量是否足够,不足时会进行扩容,以避免频繁扩容带来的性能损耗。扩容过程中涉及数据的移动和复制,以保持数据的连续性。
迭代器方面,ArrayList 提供了两种迭代器,遵循 Java 的 Iterator 规范。在迭代过程中,迭代器具备 fail-fast 机制,可以检测并处理并发修改数组的情况,确保数据的一致性。
序列化过程是 ArrayList 的关键特性之一,它重写了 JDK 的序列化逻辑,只序列化有效元素的数组部分,避免了不必要的内存占用。
在 clone() 方法中,ArrayList 需要实现深拷贝,避免原对象与克隆对象之间的相互影响,确保数据独立。
关于 ArrayList 的线程安全,有多种实现方式,例如使用 synchronized 关键字、提供 CopyOnWriteArrayList 类等。
另一个 ArrayList,即 Arrays#ArrayList,实际上是 Arrays 类的一部分,用于数组与 List 之间的转换。其底层实现与 ArrayList 类似,但主要用于数组操作。
讨论 ArrayList 是否能完全替代数组时,需要考虑性能、内存使用、类型安全等因素。在大多数业务开发场景中,ArrayList 是更好的选择,因为它提供了更高级的抽象和便利性。
通过解析 ArrayList 的源码和实现细节,我们能更好地理解其工作原理和局限性,从而在实际开发中做出更为合理的选择。在后续文章中,我们将深入探讨 ArrayList 的孪生兄弟 —— LinkedList,敬请期待。
arraylist为ä»ä¹çº¿ç¨ä¸å®å ¨
é¦å 说ä¸ä¸ä»ä¹æ¯çº¿ç¨ä¸å®å ¨ï¼çº¿ç¨å®å ¨å°±æ¯å¤çº¿ç¨è®¿é®æ¶ï¼éç¨äºå éæºå¶ï¼å½ä¸ä¸ªçº¿ç¨è®¿é®è¯¥ç±»çæ个æ°æ®æ¶ï¼è¿è¡ä¿æ¤ï¼å ¶ä»çº¿ç¨ä¸è½è¿è¡è®¿é®ç´å°è¯¥çº¿ç¨è¯»åå®ï¼å ¶ä»çº¿ç¨æå¯ä½¿ç¨ãä¸ä¼åºç°æ°æ®ä¸ä¸è´æè æ°æ®æ±¡æã线ç¨ä¸å®å ¨å°±æ¯ä¸æä¾æ°æ®è®¿é®ä¿æ¤ï¼æå¯è½åºç°å¤ä¸ªçº¿ç¨å åæ´æ¹æ°æ®é ææå¾å°çæ°æ®æ¯èæ°æ®ã å¦å¾ï¼Listæ¥å£ä¸é¢æ两个å®ç°ï¼ä¸ä¸ªæ¯ArrayListï¼å¦å¤ä¸ä¸ªæ¯vectorã ä»æºç çè§åº¦æ¥çï¼å 为Vectorçæ¹æ³åå äºï¼synchronized å ³é®åï¼ä¹å°±æ¯åæ¥çææï¼sunå ¬å¸å¸æVectoræ¯çº¿ç¨å®å ¨çï¼èå¸æarraylistæ¯é«æçï¼ç¼ºç¹å°±æ¯å¦å¤çä¼ç¹ã 说ä¸åçï¼ç¾åº¦çï¼å¾å¥½ç解ï¼ï¼ ä¸ä¸ª ArrayList ï¼å¨æ·»å ä¸ä¸ªå ç´ çæ¶åï¼å®å¯è½ä¼æ两æ¥æ¥å®æï¼
1. å¨ Items[Size] çä½ç½®åæ¾æ¤å ç´ ï¼
2. å¢å¤§ Size çå¼ã
å¨å线ç¨è¿è¡çæ åµä¸ï¼å¦æ Size = 0ï¼æ·»å ä¸ä¸ªå ç´ åï¼æ¤å ç´ å¨ä½ç½® 0ï¼èä¸ Size=1ï¼
èå¦ææ¯å¨å¤çº¿ç¨æ åµä¸ï¼æ¯å¦æ两个线ç¨ï¼çº¿ç¨ A å å°å ç´ åæ¾å¨ä½ç½® 0ãä½æ¯æ¤æ¶ CPU è°åº¦çº¿ç¨Aæåï¼çº¿ç¨ B å¾å°è¿è¡çæºä¼ã线ç¨Bä¹åæ¤ ArrayList æ·»å å ç´ ï¼å 为æ¤æ¶ Size ä»ç¶çäº 0 ï¼æ³¨æå¦ï¼æ们å设çæ¯æ·»å ä¸ä¸ªå ç´ æ¯è¦ä¸¤ä¸ªæ¥éª¤å¦ï¼è线ç¨Aä» ä» å®æäºæ¥éª¤1ï¼ï¼æ以线ç¨Bä¹å°å ç´ åæ¾å¨ä½ç½®0ãç¶å线ç¨Aå线ç¨Bé½ç»§ç»è¿è¡ï¼é½å¢å Size çå¼ã
é£å¥½ï¼ç°å¨æ们æ¥çç ArrayList çæ åµï¼å ç´ å®é ä¸åªæä¸ä¸ªï¼åæ¾å¨ä½ç½® 0ï¼è Size å´çäº 2ãè¿å°±æ¯â线ç¨ä¸å®å ¨âäºã
示ä¾ç¨åºï¼
package test;
import java.util.ArrayList;
import java.util.List;
public class ArrayListInThread implements Runnable {
List<String> list1 = new ArrayList<String>();// not thread safe
// List<String> list1 = Collections.synchronizedList(new ArrayList<String>());// thread safe
public void run() {
try {
Thread.sleep((int)(Math.random() * 2));
}
catch (InterruptedException e) {
e.printStackTrace();
}
list1.add(Thread.currentThread().getName());
}
public static void main(String[] args) throws InterruptedException {
ThreadGroup group = new ThreadGroup("mygroup");
ArrayListInThread t = new ArrayListInThread();
for (int i = 0; i < ; i++) {
Thread th = new Thread(group, t, String.valueOf(i));
th.start();
}
while (group.activeCount() > 0) {
Thread.sleep();
}
System.out.println();
System.out.println(t.list1.size()); // it should be if thread safe collection is used.
}
}