Java ArrayList解析

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++;
            }
        }
    }

}

引用https://www.cnblogs.com/ccgjava/p/6347425.html?utm_source=itdadao&utm_medium=referral

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();
    }
}

引用自https://www.cnblogs.com/nevermorewang/p/9368431.html

posted @ 2019-08-21 16:51  Elinlinlin  阅读(351)  评论(0编辑  收藏  举报