1 - 使用集合的好处
数组:长度固定、一旦指定,不能修改
保存同类型的元素
增加、删除元素比较麻烦
int [ ] ints = new int [ 1 ] ;
ints[ 0 ] = 1 ;
int [ ] ints1 = new int [ ints. length + 1 ] ;
for ( int i = 0 ; i < ints. length; i ++ ) {
ints1[ i] = ints[ i] ;
}
使用集合可以保存任意多的不同类型的元素
集合体系图
虚线代表接口,实现代表继承关系
Iterator
迭代器,遍历Collection 中的元素
iterator本身不存放元素
# 迭代器的使用
List l = new ArrayList < > ( ) ;
l. add ( "1" ) ;
Iterator iterator = l. iterator ( ) ;
while ( iterator. hasNext ( ) ) {
String s = ( String ) iterator. next ( ) ;
System . out. println ( s) ;
}
# 调用next ( ) 之前必须先调用hashNext ( ) ,否则会抛出NoSuchElementException ( )
List l = new ArrayList < > ( ) ;
l. add ( "1" ) ;
l. add ( "2" ) ;
Iterator iterator = l. iterator ( ) ;
while ( true ) {
String s = ( String ) iterator. next ( ) ;
System . out. println ( s) ;
}
Exception in thread "main" java. util. NoSuchElementException
增强for循环可以替代Iterator
List
1 - 实现了List 的子接口和List 类存入元素和取出元素顺序一致,是有序的,元素可以重复
List类的三种遍历方式
List l = new ArrayList < > ( ) ;
l. add ( "1" ) ;
l. add ( "2" ) ;
Iterator iterator = l. iterator ( ) ;
while ( true ) {
String s = ( String ) iterator. next ( ) ;
System . out. println ( s) ;
}
for ( int i = 0 ; i < l. size ( ) ; i++ ) {
l. get ( i) ;
}
for ( Object str : l) {
System . out. println ( str) ;
}
ArrayList
# ArrayList 无参构造方法,初始化容量是10
# ArrayList 可以存储null ,并且可以存储多个null
List l = new ArrayList < > ( ) ;
l. add ( "1" ) ;
l. add ( "2" ) ;
l. add ( null ) ;
l. add ( null ) ;
Iterator iterator = l. iterator ( ) ;
while ( iterator. hasNext ( ) ) {
System . out. println ( iterator. next ( ) == null ) ;
}
#ArrayList 基本等同于Vector ,是线程不安全的,效率高,多线程下不建议使用ArrayList , 是因为底层方法
没有Synchornized 修饰
public boolean add ( E e) {
modCount++ ;
add ( e, elementData, size) ;
return true ;
}
ArrayList底层源码分析(JDK 11)
基本属性
transient Object [ ] elementData;
private int size;
add()方法-在数组尾部添加元素
public boolean add ( E e) {
modCount++ ;
add ( e, elementData, size) ;
return true ;
}
private void add ( E e, Object [ ] elementData, int s) {
if ( s == elementData. length)
elementData = grow ( ) ;
elementData[ s] = e;
size = s + 1 ;
}
private Object [ ] grow ( ) {
return grow ( size + 1 ) ;
}
private Object [ ] grow ( int minCapacity) {
return elementData = Arrays . copyOf ( elementData,
newCapacity ( minCapacity) ) ;
}
private int newCapacity ( int minCapacity) {
int oldCapacity = elementData. length;
int newCapacity = oldCapacity + ( oldCapacity >> 1 ) ;
if ( newCapacity - minCapacity <= 0 ) {
if ( elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
return Math . max ( DEFAULT_CAPACITY, minCapacity) ;
if ( minCapacity < 0 )
throw new OutOfMemoryError ( ) ;
return minCapacity;
}
return ( newCapacity - MAX_ARRAY_SIZE <= 0 )
? newCapacity
: hugeCapacity ( minCapacity) ;
}
remove(index i)
public E remove ( int index) {
Objects . checkIndex ( index, size) ;
final Object [ ] es = elementData;
@SuppressWarnings ( "unchecked" )
E oldValue = ( E ) es[ index] ;
fastRemove ( es, index) ;
return oldValue;
}
private void fastRemove ( Object [ ] es, int i) {
modCount++ ;
final int newSize;
if ( ( newSize = size - 1 ) > i)
System . arraycopy ( es, i + 1 , es, i, newSize - i) ;
es[ size = newSize] = null ;
}
remove(e)
public boolean remove ( Object o) {
final Object [ ] es = elementData;
final int size = this . size;
int i = 0 ;
found: {
if ( o == null ) {
for ( ; i < size; i++ )
if ( es[ i] == null )
break found;
} else {
for ( ; i < size; i++ )
if ( o. equals ( es[ i] ) )
break found;
}
return false ;
}
fastRemove ( es, i) ;
return true ;
}
ArrayList 底层是数组,在删除和添加元素时,都需要对数组进行扩容或者缩容,在这个过程中
由于数组中元素是连续的,内存空间必须一次性分配够,需要重新分配一块更大的空间,再把数据全部复制过去,
时间复杂度是O ( N ) 。ArrayList 查询快,增删慢
# 增强for 循环中,删除元素会抛异常
ArrayList < String > l = new ArrayList < String > ( ) ;
l. add ( "1" ) ;
l. add ( "2" ) ;
l. add ( "3" ) ;
for ( String str : l) {
if ( str. equals ( "1" ) ) {
l. remove ( str) ;
}
}
Exception in thread "main" java. util. ConcurrentModificationException
at java. base/ java. util. ArrayList $Itr . checkForComodification ( ArrayList . java: 1043 )
at java. base/ java. util. ArrayList $Itr . next ( ArrayList . java: 997 )
增强for 循环底层是迭代器实现的,List 在调用Iterator 方法时,维护了一个int expectedModCount = modCount;
modCount表示集合被修改的次数,expectedModCount只在add时赋值,因此在删除后,expectedModCount != modCount,
此时会报错ConcurrentModificationException 。
遍历修改集合时应该使用:
while ( iterator. hasNext ( ) ) {
String a = "1" ;
if ( iterator. next ( ) . equals ( a) ) {
iterator. remove ( ) ;
}
}
List < String > a = new ArrayList < String > ( ) ;
a. add ( "a" ) ;
a. add ( "b" ) ;
a. add ( "c" ) ;
final ArrayList < String > lists = new ArrayList < String > (
a) ;
Thread t = new Thread ( new Runnable ( ) {
int count = - 1 ;
@Override
public void run ( ) {
while ( true ) {
lists. add ( count++ + "" ) ;
}
}
} ) ;
t. setDaemon ( true ) ;
t. start ( ) ;
Thread . currentThread ( ) . sleep ( 300 ) ;
for ( String s : lists) {
System . out. println ( s) ;
}
1 - ArrayList 不是线程安全的
2 - 使用Collections . synchornizedList ( new ArrayList < > ( ) ) 或者
Vector 或者CopyOnWriteArrayList
List < String > list = new CopyOnWriteArrayList < String > ( ) ;
list. add ( "1" ) ;
Object [ ] es = getArray ( ) ;
* int len = es. length;
* es = Arrays . copyOf ( es, len + 1 ) ;
* es[ len] = e;
* setArray ( es) ;
* return true ;
* }
* }
* /
list. add ( "1" ) ;