ArrayList继承了AbstractList,实现了List, RandomAccess, Cloneable, java.io.Serializable
ArrayList的底层数据结构是数组。ArrayList初始化时创建一个定长的数组,当添加元素越界时,会自动扩容,以此避免数组越界;由于数组的结构支持for循环访问,并以RandomAccess接口表明, for循环比迭代器模式效率高
1.常用方法
默认的无参构造方法并不开辟数组空间;而在添加元素时开辟长度;
查询:get(), indexOf()
修改:set()
删除:remove(), removeAll();
增加:add()
grow() 是数组扩容的实现方法,利用Arrays.copyOf创建新的数组并修改引用关系。所以尽量在初始化ArrayList时赋予合适的长度
toArray();
clone();
foreach();
2.迭代器模式-Iterator
迭代器模式是设计模式之一,迭代器的作用是提供一种顺序访问集合内的数据,又不暴露集合的内部结构
public interface ListIterator<E> extends Iterator<E>
private class ListItr extends Itr implements ListIterator<E>
public Iterator<E> iterator() {
return new Itr();
}
ArrayList的Iterator实现类是内部类ListItr,调用迭代器会返回ListItr的新实例对象
3.fast-fail机制
在多线程环境下,利用迭代器模式访问集合数据时,如果访问过程中,数据被其他线程修改,会抛出ConcurrentModificationException异常
这是一种简易的、有效的、快捷的检测错误机制,防止出现该错误应该使用线程安全的集合类
import java.util.*;
import java.util.concurrent.*;
/*
* @desc java集合中Fast-Fail的测试程序。
*
* fast-fail事件产生的条件:当多个线程对Collection进行操作时,若其中某一个线程通过iterator去遍历集合时,该集合的内容被其他线程所改变;则会抛出ConcurrentModificationException异常。
* fast-fail解决办法:通过util.concurrent集合包下的相应类去处理,则不会产生fast-fail事件。
*
* 本例中,分别测试ArrayList和CopyOnWriteArrayList这两种情况。ArrayList会产生fast-fail事件,而CopyOnWriteArrayList不会产生fast-fail事件。
* (01) 使用ArrayList时,会产生fast-fail事件,抛出ConcurrentModificationException异常;定义如下:
* private static List<String> list = new ArrayList<String>();
* (02) 使用时CopyOnWriteArrayList,不会产生fast-fail事件;定义如下:
* private static List<String> list = new CopyOnWriteArrayList<String>();
*
* @author skywang
*/
public class FastFailTest {
private static List<String> list = new ArrayList<String>();
//private static List<String> list = new CopyOnWriteArrayList<String>();
public static void main(String[] args) {
// 同时启动两个线程对list进行操作!
new ThreadOne().start();
new ThreadTwo().start();
}
private static void printAll() {
System.out.println("");
String value = null;
Iterator iter = list.iterator();
while(iter.hasNext()) {
value = (String)iter.next();
System.out.print(value+", ");
}
}
/**
* 向list中依次添加0,1,2,3,4,5,每添加一个数之后,就通过printAll()遍历整个list
*/
private static class ThreadOne extends Thread {
public void run() {
int i = 0;
while (i<6) {
list.add(String.valueOf(i));
printAll();
i++;
}
}
}
/**
* 向list中依次添加10,11,12,13,14,15,每添加一个数之后,就通过printAll()遍历整个list
*/
private static class ThreadTwo extends Thread {
public void run() {
int i = 10;
while (i<16) {
list.add(String.valueOf(i));
printAll();
i++;
}
}
}
}
3.可分割迭代器-Spliterator
Spliterator是一个可分割迭代器,目的是并行遍历元素,补充顺序迭代器Iterator的缺陷
通过切分集合、多线程同时分别执行,实现并行
//单个对元素执行给定的动作,如果有剩下元素未处理返回true,否则返回false
boolean tryAdvance(Consumer<? super T> action);
//对每个剩余元素执行给定的动作,依次处理,直到所有元素已被处理或被异常终止。默认方法调用tryAdvance方法
default void forEachRemaining(Consumer<? super T> action) {
do { } while (tryAdvance(action));
}
//对任务分割,返回一个新的Spliterator迭代器
Spliterator<T> trySplit();
//用于估算还剩下多少个元素需要遍历
long estimateSize();
//当迭代器拥有SIZED特征时,返回剩余元素个数;否则返回-1
default long getExactSizeIfKnown() {
return (characteristics() & SIZED) == 0 ? -1L : estimateSize();
}
//返回当前对象有哪些特征值
int characteristics();
//是否具有当前特征值
default boolean hasCharacteristics(int characteristics) {
return (characteristics() & characteristics) == characteristics;
}
//如果Spliterator的list是通过Comparator排序的,则返回Comparator
//如果Spliterator的list是自然排序的 ,则返回null
//其他情况下抛错
default Comparator<? super T> getComparator() {
throw new IllegalStateException();
}
public class Atest {
AtomicInteger count = new AtomicInteger(0);
List<String> strList = createList();
Spliterator spliterator = strList.spliterator();
/**
* 多线程计算list中数值的和
* 测试spliterator遍历
*/
@Test
public void mytest(){
for(int i=0;i<4;i++){
new MyThread().start();
}
try {
Thread.sleep(15000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("结果为:" + count);
}
class MyThread extends Thread{
@Override
public void run() {
String threadName = Thread.currentThread().getName();
System.out.println("线程"+threadName+"开始运行-----");
spliterator.trySplit().forEachRemaining(new Consumer() {
@Override
public void accept(Object o) {
if(isInteger((String)o)){
int num = Integer.parseInt(o +"");
count.addAndGet(num);
System.out.println("数值:"+num+"------"+threadName);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
System.out.println("线程"+threadName+"运行结束-----");
}
}
private List<String> createList(){
List<String> result = new ArrayList<>();
for(int i=0; i<100; i++){
if(i % 10 == 0){
result.add(i+"");
}else{
result.add("aaa");
}
}
return result;
}
public static boolean isInteger(String str) {
Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
return pattern.matcher(str).matches();
}
}