53 java集合和泛型_3 _List实现类 _ ArrayList
List实现类
- ArrayList【重点】:(内部实质也是数组)
- 数组结构实现,查询快、增刪慢;
- JDK1.2版本,运行效率快、线程不安全。
- LinkedList:链表结构实现,增删快,查询慢
- Vector:(基本不再使用)
- 数组结构实现,查询快、增删慢;
- JDK1. 0版本,运行效率慢、线程安全。
ArrayList的使用
List
接口的大小可变数组的实现。实现了所有可选列表操作,并允许包括 null
在内的所有元素。除了实现 List
接口外,此类还提供一些方法来操作内部用来存储列表的数组的大小。
代码:
package com.wlw.collection.list;
import com.wlw.collection.Student;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;
/**
* ArrayList的使用:
* 存储结构:数组,查询快,增删慢
* 有序 有下标 可重复
*/
public class ArrayList_Demo {
public static void main(String[] args) {
ArrayList arrayList = new ArrayList(); //此时size 容量都为0
Student s1 = new Student("张三",20);
Student s2 = new Student("张无忌",21);
Student s3 = new Student("张大头",22);
//1.添加
arrayList.add(s1);
arrayList.add(s2);
arrayList.add(s3);
System.out.println("元素个数:"+arrayList.size());
System.out.println(arrayList.toString());
//2.删除
/*
补充知识点:
arrayList.remove(new Student("张三",20)); 正常情况下这是新创建的一个对象,不会是删除上面的s1
假如我们想通过 arrayList.remove(new Student("张三",20));这种方式来删除上面的s1
需要 在Student 类中重写equals方法,因为remove()方法源码中也是通过equals方法来判断,是否要删除
重写equals()方法代码见 com.wlw.collection.Student;
*/
//arrayList.remove(s1);
/*
arrayList.remove(new Student("张三",20));
System.out.println("删除之后,元素个数:"+arrayList.size());
System.out.println("删除之后:"+arrayList.toString());
*/
//3.遍历【重点】
//3.1
System.out.println("---------------3.1 普通for循环---------------");
for (int i = 0; i < arrayList.size();i++){
System.out.println(arrayList.get(i));
}
//3.2增强for循环
System.out.println("---------------3.2增强for循环---------------");
for (Object obj : arrayList) {
Student s = (Student) obj;
System.out.println(s.toString());
}
//3.3 Iterator迭代器
System.out.println("---------------3.3 Iterator迭代器---------------");
Iterator iterator = arrayList.iterator();
while (iterator.hasNext()){
//Object o = iterator.next();
//Student s = (Student)o;
Student s = (Student)iterator.next();
System.out.println(s.toString());
}
//3.4 列表迭代器ListIterator,和Iterator的区别:ListIterator可以向前也可以向后遍历、添加、修改、删除元素
System.out.println("---------------3.4 列表迭代器ListIterator---------------");
ListIterator listIterator = arrayList.listIterator();
System.out.println("从前往后");
while (listIterator.hasNext()){
//Student s = (Student)listIterator.next();
System.out.println( listIterator.nextIndex() +":"+ listIterator.next());
}
System.out.println("从后往前");
while (listIterator.hasPrevious()){
System.out.println(listIterator.previousIndex()+":"+listIterator.previous());
}
//4.判断
System.out.println(arrayList.contains(s1)); //true
System.out.println(arrayList.isEmpty()); //false
//5.查找
System.out.println(arrayList.indexOf(s2)); //返回元素对应的下标
}
}
/*
执行结果:
元素个数:3
[Student{name='张三', age=20}, Student{name='张无忌', age=21}, Student{name='张大头', age=22}]
---------------3.1 普通for循环---------------
Student{name='张三', age=20}
Student{name='张无忌', age=21}
Student{name='张大头', age=22}
---------------3.2增强for循环---------------
Student{name='张三', age=20}
Student{name='张无忌', age=21}
Student{name='张大头', age=22}
---------------3.3 Iterator迭代器---------------
Student{name='张三', age=20}
Student{name='张无忌', age=21}
Student{name='张大头', age=22}
---------------3.4 列表迭代器ListIterator---------------
从前往后
0:Student{name='张三', age=20}
1:Student{name='张无忌', age=21}
2:Student{name='张大头', age=22}
从后往前
2:Student{name='张大头', age=22}
1:Student{name='张无忌', age=21}
0:Student{name='张三', age=20}
true
false
1
*/
遇到的问题:ListIterator(列表迭代器)中的next (),nextIndex() , previous(),previousIndex()
//问题:上面listIterator如果这样写,结果输出的下标会变的
ListIterator listIterator = arrayList.listIterator();
System.out.println("从前往后");
while (listIterator.hasNext()){
Student s = (Student)listIterator.next();
System.out.println( listIterator.nextIndex() +":"+ s.toString());
}
/*
执行结果:
从前往后
1:Student{name='张三', age=20}
2:Student{name='张无忌', age=21}
3:Student{name='张大头', age=22}
*/
/*
一开始时,nextIndex()=0,previousIndex()=-1
上面代码第五行Student s = (Student)listIterator.next();类型转换时,进行了next(),
此时,游标指针往右移了一位,此时nextIndex()=1,previousIndex()=0,
在这之后,我们再输出打印,就变成了上面的输出结果。
如下图:
*/
ArrayList部分源码分析
private static final int DEFAULT_CAPACITY = 10; //默认容量为10
/*
没有向集合添加元素时,容量为0,是一个空数组,
当添加任意一个元素后,就变成了10
每次扩容大小是原来的1.5倍
*/
transient Object[] elementData; //存放元素的数组
private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
private int size;//实际的元素个数
//无参构造
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; //空数组赋值为数组
}
//add() 方法
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!! 增加容量
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); //(10,1)
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}