List接口
List接口继承了Collection接口
List接口存放的元素有序且允许有重复,Set接口存放的元素则是无序不重复
说明:
“有序”是指元素的存入顺序和和取出顺序相同,“无序”则是指存入顺序和取出顺序不同
List<String> list = new ArrayList<String>();
Set<String> set = new HashSet<String>();
Set<Integer> setInt = new HashSet<Integer>();
list.add("h");
list.add("e");
list.add("l");
list.add("l");
list.add("o");
set.add("h");
set.add("e");
set.add("l");
set.add("l");
set.add("o");
setInt.add(3);
setInt.add(2);
setInt.add(0);
setInt.add(5);
setInt.add(1);
for (int i = 0 ; i < list.size(); i++ ) {
System.out.print(list.get(i));
}
System.out.println();
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()) {
System.out.print(iterator.next());
}
System.out.println();
Iterator<Integer> iteratorInt = setInt.iterator();
while (iteratorInt.hasNext()) {
System.out.print(iteratorInt.next());
}
输出结果:
hello
eolh
01235
可以看到当把String类型的相同数据分别放到List和Set集合中,再取出来两者就不一样了。List集合按照存入的顺序取出;Set集合则按照英文字母的顺序取出。
如果存入Set集合的数据是Integer类型,则按照整数从小到大的顺序取出。
常用方法
- 添加
boolean add(E e);
boolean addAll(Collection< ? extends E> c); - 删除
boolean remove(Object o);
boolean removeAll(Collection< ?> c);
boolean retainAll(Collection< ?> c); - 是否包含
boolean contains(Object o)
boolean containsAll(Collection< ? > c) - 清空
void clear(); - 获取单个元素和迭代器
E get(int index);
Iterator< E > iterator();//也可以用for循环依次获取每个元素 - 判空和获取大小
int size();
boolean isEmpty();
List接口的实现类ArrayList
ArrayList是List接口最常用到的一个实现类,ArrayList列表对象实际上存储在一个Object类型的数组,当列表对象变化时,新建一个数组,再通过copyof方法覆盖旧的数组,所以ArrayList就像一个可变大小的数组。
ArrayList源码 :
ArrayList属性:
private transient Object[] elementData;//ArrayList内的元素
private int size;//元素的数量
ArrayList提供了三个构造方法:
/**如果指定了初识的容量,构造一个指定大小的空列表*/
public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);
this.elementData = new Object[initialCapacity];//创建一个长度为指定容量的临时数组
}
private static final Object[] EMPTY_ELEMENTDATA = {};
/**如果未指定初识容量,则构造一个默认容量的空列表*/
public ArrayList() {
super();
this.elementData = EMPTY_ELEMENTDATA//现在的临时数组还是一个空数组,会在添加数据的时候进行判断并设置初识的容量
}
//构造一个包含指定Collection元素的列表,即ArrayList放Collection元素
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();//初始化临时数组
size = elementData.length;//列表长度
//可能临时数组不是Object[]类型,
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
}
public Object[] toArray() {
return Arrays.copyOf(elementData, size);
}
添加元素:
private static final int DEFAULT_CAPACITY = 10;//初始容量
/*添加*/
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;//在数组的尾部添加元素
return true;
}
/*确保容量*/
private void ensureCapacityInternal(int minCapacity) {
/*判断是否指定初始的容量*/
if (elementData == EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);//比较默认容量和(元素数量size+1)的大小,取较大的值作为添加元素后ArrayList的容量
}
ensureExplicitCapacity(minCapacity);
}
protected transient int modCount = 0;//定义在AbstractList接口中
/*确定容量*/
private void ensureExplicitCapacity(int minCapacity) {
modCount++;//The number of times this list has been structurally modified.
//这是对modCount的解释,意为记录list结构被改变的次数
// 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);//新的容量:(元素数量+元素数量/2)
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;//添加元素后(size+1)未超过给定的容量,不用增加容量
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);//elementData指向新容量的数组,旧的数组被丢弃
}
/*能分配的最大的容量*/
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
/**
* The maximum size of array to allocate.
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
* 减去8是因为VMs保留了一些头部字段
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
//在java.lang.Integer类中常量MIN_VALUE、MAX_VALUE如下:
public static final int MIN_VALUE = 0x80000000;//整型取值区间下界:-2147483648
public static final int MAX_VALUE = 0x7fffffff;//整型取值区间上界:2147483647
删除元素:分为按位置删除和按元素删除
根据位置删除:
public E remove(int index) {
rangeCheck(index);//检查是否超过ArrayList长度
modCount++;//记录list结构被改变的次数
E oldValue = elementData(index);//保留要删除的元素
int numMoved = size - index - 1;设置新数组长度-1
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index, numMoved);要删除元素后面的值往前移一位
elementData[--size] = null; // clear to let GC do its work末尾元素置null回收
return oldValue;//返回要删除的元素的值
}
/*检测位置*/
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
根据元素删除:
public boolean remove(Object o) {
if (o == null) {//删除null的元素
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
/*删除元素*/
private void fastRemove(int index) {
//不用进行边界处理
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index, numMoved);
elementData[--size] = null; // clear to let GC do its work
}
根据元素删除和根据位置删除的区别:
根据元素删除返回的是true或false
根据位置删除返回的是要删除的元素