一、ArrayList
private static final int DEFAULT_CAPACITY = 10 ;
private static final Object [ ] EMPTY_ELEMENTDATA = { } ;
private static final Object [ ] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = { } ;
transient Object [ ] elementData;
private int size;
private static final int MAX_ARRAY_SIZE = Integer . MAX_VALUE - 8 ;
无参构造器 指定数据大小的构造器 ,如果大于0创建一个新的数组,如果等于0,赋值默认大小的数组 添加元素方法add(E e)
public boolean add ( E e) {
ensureCapacityInternal ( size + 1 ) ;
elementData[ size++ ] = e;
return true ;
}
private static int calculateCapacity ( Object [ ] elementData, int minCapacity) {
if ( elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math . max ( DEFAULT_CAPACITY, minCapacity) ;
}
return minCapacity;
}
private void ensureCapacityInternal ( int minCapacity) {
ensureExplicitCapacity ( calculateCapacity ( elementData, minCapacity) ) ;
}
private void ensureExplicitCapacity ( int minCapacity) {
modCount++ ;
if ( minCapacity - elementData. length > 0 )
grow ( minCapacity) ;
}
private void grow ( int minCapacity) {
int oldCapacity = elementData. length;
int newCapacity = oldCapacity + ( oldCapacity >> 1 ) ;
if ( newCapacity - minCapacity < 0 )
newCapacity = minCapacity;
if ( newCapacity - MAX_ARRAY_SIZE > 0 )
newCapacity = hugeCapacity ( minCapacity) ;
elementData = Arrays . copyOf ( elementData, newCapacity) ;
}
private static int hugeCapacity ( int minCapacity) {
if ( minCapacity < 0 )
throw new OutOfMemoryError ( ) ;
return ( minCapacity > MAX_ARRAY_SIZE) ?
Integer . MAX_VALUE :
MAX_ARRAY_SIZE;
}
指定位置添加元素add(int index, E element) ,list长度很大时尽量少使用,每次添加都会导致数组复制效率很低
public void add ( int index, E element) {
rangeCheckForAdd ( index) ;
ensureCapacityInternal ( size + 1 ) ;
System . arraycopy ( elementData, index, elementData, index + 1 ,
size - index) ;
elementData[ index] = element;
size++ ;
}
List list = new ArrayList<>(Arrays.asList(1,2,3,1,2,1,3,1,1,2,2,2,2,3,3,3)); 怎么删除List中所有为1的数据?
List < Integer > list = new ArrayList < > ( Arrays . asList ( 1 , 2 , 3 , 1 , 2 , 1 , 3 , 1 , 1 , 2 , 2 , 2 , 2 , 3 , 3 , 3 ) ) ;
Iterator < Integer > iterator = list. iterator ( ) ;
while ( iterator. hasNext ( ) ) {
Integer next = iterator. next ( ) ;
if ( next == 1 ) {
iterator. remove ( ) ;
}
}
List < Integer > list = new ArrayList < > ( Arrays . asList ( 1 , 2 , 3 , 1 , 2 , 1 , 3 , 1 , 1 , 2 , 2 , 2 , 2 , 3 , 3 , 3 ) ) ;
for ( int i = 0 ; i < list. size ( ) ; i++ ) {
if ( list. get ( i) == 1 ) {
list. remove ( i) ;
}
}
List < Integer > list = new ArrayList < > ( Arrays . asList ( 1 , 2 , 3 , 1 , 2 , 1 , 3 , 1 , 1 , 2 , 2 , 2 , 2 , 3 , 3 , 3 ) ) ;
for ( Integer i: list) {
if ( i == 1 ) {
list. remove ( i) ;
}
}
public E remove ( int index) {
rangeCheck ( index) ;
modCount++ ;
E oldValue = elementData ( index) ;
int numMoved = size - index - 1 ;
if ( numMoved > 0 )
System . arraycopy ( elementData, index+ 1 , elementData, index,
numMoved) ;
elementData[ -- size] = null ;
return oldValue;
}
public E next ( ) {
checkForComodification ( ) ;
int i = cursor;
if ( i >= size)
throw new NoSuchElementException ( ) ;
Object [ ] elementData = ArrayList . this . elementData;
if ( i >= elementData. length)
throw new ConcurrentModificationException ( ) ;
cursor = i + 1 ;
return ( E ) elementData[ lastRet = i] ;
}
final void checkForComodification ( ) {
if ( modCount != expectedModCount)
throw new ConcurrentModificationException ( ) ;
}
public void remove ( ) {
if ( lastRet < 0 )
throw new IllegalStateException ( ) ;
checkForComodification ( ) ;
try {
ArrayList . this . remove ( lastRet) ;
cursor = lastRet;
lastRet = - 1 ;
expectedModCount = modCount;
} catch ( IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException ( ) ;
}
}
二、Collections.synchronizedList
使用方法 List list = Collections.synchronizedList(new ArrayList()); 且该方法返回的是一个方法都加锁的对象SynchronizedList 多线程下使用for循环遍历,或者迭代器遍历必须手动加锁。
SynchronizedCollection ( Collection < E > c) {
this . c = Objects . requireNonNull ( c) ;
mutex = this ;
}
SynchronizedCollection ( Collection < E > c, Object mutex) {
this . c = Objects . requireNonNull ( c) ;
this . mutex = Objects . requireNonNull ( mutex) ;
}
public int size ( ) {
synchronized ( mutex) { return c. size ( ) ; }
}
public Iterator < E > iterator ( ) {
return c. iterator ( ) ;
}
public boolean add ( E e) {
synchronized ( mutex) { return c. add ( e) ; }
}
public boolean remove ( Object o) {
synchronized ( mutex) { return c. remove ( o) ; }
}
同时操作add和contains方法时,两个单独的方法虽然是线程安全的。但是两个方法同时调用却不是原子性操作,也需要加锁
List list = Collections . synchronizedList ( new ArrayList < > ( ) ) ;
for ( int i = 0 ; i < 50 ; i++ ) {
Thread thread = new Thread ( new Runnable ( ) {
@Override
public void run ( ) {
synchronized ( list) {
if ( ! list. contains ( 1 ) ) {
list. add ( 1 ) ;
}
}
}
} ) ;
thread. start ( ) ;
}
三、CopyOnWriteArrayList
对CopyOnWriteArrayList进行修改,会先拷贝一个新数组然后在其上进行操作。修改后的内容其他线程不会及时看到,只能等修改操作完成后才看到。所以如果业务需要看到及时的数据CopyOnWriteArrayList是适用这个业务的。而且每次修改都会有拷贝数组的操作,所以也不适用有大量修改的业务。 因为修改操作是在新数组上进行,对原数组不会影响。所以读取方法不需要加锁,读取操作性能很快。CopyOnWriteArrayList适用读取操作多,修改操作少的业务。 多线程下使用for循环遍历,不需要手动加锁,因为遍历时,即使有线程修改也是修改复制的新数组
public E get ( int index) {
return get ( getArray ( ) , index) ;
}
public boolean add ( E e) {
final ReentrantLock lock = this . lock;
lock. lock ( ) ;
try {
Object [ ] elements = getArray ( ) ;
int len = elements. length;
Object [ ] newElements = Arrays . copyOf ( elements, len + 1 ) ;
newElements[ len] = e;
setArray ( newElements) ;
return true ;
} finally {
lock. unlock ( ) ;
}
}
参考内容
https://www.jianshu.com/p/0b3e5df6fe57