List本身也是一个接口,是一个元素存入和取出有顺序的,且元素可以重复的一个集合接口。
此接口的用户可以对列表中每个元素的插入位置进行精确地控制,用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。
方式一:通过循环+get来配合遍历
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
方式二:使用listIterator()迭代遍历 ListIterator: 允许程序员按任一方向遍历列表、迭代期间修改列表,并获得迭代器在列表中的当前位置。 boolean hasNext():判断是否存在下一个元素 Object next():返回集合的下一个元素 boolean hasPrevious():判断是否存在上一个元素 Object previous():返回集合的上一个元素
ArrayList:底层维护的是一个Object数组,特点:查询速度快,增删比较慢
LinkedList:底层维护的是一个链表,特点:查询速度比较慢,增删速度快
Vector:一个非常古老的集合,JDK1.O版本就诞生看,大部分功能和ArrayList是一致的,区别是这玩意是线程安全的。
但是因为结构的问题,他的处理效率要远远低于ArrayList,一般尽量避免使用,因为即使要线程安全,我们在多线程的时候可以解决这个问题。
集合遍历 方式一:将集合转换成Object数组,然后数组进行遍历
Object [] obj = con.toArray();
for (int i = 0; i < obj.length; i++) {
String s = (String)obj;
System.out.println(s);
}
方式二:使用jdk5的foreach循环
for(Object str: con){
String s = (String) str;
System.out.println(s);
}
导语:底层其实还是采用的迭代器,无需转换数组,无需确定索引。 方式三:使用Iterator
Iterator it = con.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
Iterator被称之为迭代器(设计模式一种),主要的作用是用于遍历Collection集合当中的元素
Collection其实已经继承Iterable的接口,而Iterable有有一个Iterator的方法,这个方法又实现了Iterator的接口。
Iterator的方法: boolean hasNext() 判断集合当中是否存在下一个元素 Object next() 获取下一个元素的内容 void remove() 移除迭代最后一个元素
ArrayList类的属性:
private transient Object[] elementData;
private int size;
(1)ConcurrentModificationException
当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。
ArrayList本身其实也是采用快速失败机制进行处理,通过一个modCount这个参数来进行实现,Iterator本身和ArrayList是没有直接关联的。
但是有一种情况可能会出现并发现象(同一个时间点同时执行了某一件事),当iterator已经在hasNext的时候就已经判断了不存在下一个元素,而ArrayList.add()又恰好在这同一时刻又新添加了元素,所以可能造成数据错乱,JDK本身就考虑好了这件事,他使用了一个计数器modCount。
迭代器的执行和add()的执行其实都有共同去维护一个计数的过程,只要在计数过程当中,计数被修改了即迭代器立马失败,而不是冒着危险在将来一个不确定的时候再去产生异常。
解决方式:
1.使用迭代器的添加跟删除
2.不使用迭代器
(2)ArrayList在jdk7和jdk8的一些区别
ArrayList是List的可变数组的实现方式 .
Jdk7:
类似饿汉式、在创建对象,使用无参构造的时候,其实就创建了一个长度为10的一个数组进行维护
JDK8:
类似懒汉式、在创建对象,使用无参构造的时候,并没有给数组指定任何的长度,而是在第一个元素添加的时候才会去生成一个 10个长度的数组
/**
* 创建一个容量为initialCapacity的空的(size==0)对象数组
*/
public ArrayList(int initialCapacity) {
super();//即父类protected AbstractList() {}
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity:" + initialCapacity);
this.elementData = new Object[initialCapacity];
}
/** * 默认初始化一个容量为10的对象数组 */
public ArrayList() {
this(10);//即上边的public ArrayList(int initialCapacity){}构造器
}
是List子类当中,采用双向链表的一种实现方式的子类,内部不存在任何数组的声明,而是定义了链表的开端和结尾。
特有成员方法
void addFirst(E e):将元素添加到集合首位
void addLast(E e) 将元素添加到集合结尾:
E getFirst() 获取第一个元素
E getLast(E e) 获取最后一个元素
E removeFirst() 删除第一个元素
E removeLast() 删除最后一个元素
1.栈(存储方式的先进的后出)
void push(E e):依照栈结构的方式进行数据插入(压栈)
E pop() 依照栈结构的方式将数据取出(弹栈)
2.对列(先进的先出)
boolean offer(E e): 依照队列结构的方式将数据进行插入(因为对列是需要进行排队是,所有永远最后一个)
E poll() 依照队列的结构取出首位数据,并且删除
ArrayList/LinkedList本质上两者都是线程不安全的,相比线程安全的Vector来说,效率要比较快。
另外ArrayList底层维护的是一个动态数组的数据结构,而LinkedList基于一个双向链表的一个数据结构。
对于随机访问get/set,ArrayList绝对优于LinkedList,因为LinkedList要不断的移动指针。
对于新增(add)和删除(remove)数据来说,LinkedList比较有优势,因为ArrayList不断创建新的集合进行拷贝和运算。
Vector和ArrayList几乎一致,唯一的区别就是Vector是一个强同步类(synchronized) ,内存开销特别大,访问特别慢。
正常情况下ArrayList是完全可以取代Vector,因为我们自己可以手动控制任何对象是否同步。
Vecter较Array安全(原因:Vecter只允许在同一时间段运行一个线程)
Vecter在查询和增删方面的效率都不高
其余特点与ArrayList相似
因为ArrayList底层维护的是数组,所以在查询方面ArrayList的效率比较高
因为LinkedList底层维护的是链表,所以在增删方面LinkedList的效率比较高
评论