iterator(迭代器)
所有实现了Collection接口的集合类都有一个iterator()方法,用于返回一个实现了Iterator接口的对象,即可以返回一个迭代(用来遍历)
增强for循环的底层也是iterator ,
java.lang.Iterable接口,实现这个接口允许对象成为 “foreach” 语句的目标。
Java 5时Collection接口继承了java.lang.Iterable接口,因此Collection系列的集合就可以直接使用foreach循环遍历
for(元素类型 元素名: 集合名/数组名){
访问元素;
}
Collection 集合
collection常用方法:
- 1)add:添加单个元素
- 2)remove:删除指定元素
- 3)contains:查找元素是否存在
- 4)size:获取元素个数
- 5)isEmpty:判断是否为
- 6)clear:清空
- 7)addAll:添加多个元素
- 8)containsAll:查找多个元素是否都存在
- 9)removeAll:删除多个元素
----Collection: 单列集合,用来存储一个一个的对象
----List接口:存储有序的、可重复的数据。
----Arraylist :作为List接口的主要实现类:线程不安全的,效率高:底
----LinkedList:对于频繁的插入、删除操作,使用此类效率比ArrayList高
----Vector:作为List接口的古老实现类:线程安全的,教率低,底层使用object[]
----Set接口:存储无序的、不可重复的数据-->高中讲的“集合----HashSet:作为Set接口的主要实现类:线程不安全的:可以存储nulL值 ----LinkedHashSet:作为HashSet的子类: 遍历其内部数据时,可以按照添加的顺序遍历
----TreeSet :可以按照添加对象的指定属性,进行排序。
----Map接口:双列集合,用来存储一对(key - value)一对的数 -->高中函数: y = f(x,y)----HashMap:作Map的主要实现类: 线程不安全的,效率高: 存储null的key和value
----LinkedHashMap:保证在遍历map元素时,可以按照添加的顺序实现遍历。
----TreeMap:保证按照添加的key-value对进行排序,实现排序遍历。此时考虑key的自然排序或定制排序
----Hashtable:作为古老的实现类: 线程安全的,效率低:不能存储null的key和value
List
List集合所有的元素是以一种线性方式进行存储的,集合中可以有重复的元素,通过元素的equals方法,来比较是否为重复的元素
List不仅继承了collection接口的方法,还有一些自己的方法
1、添加元素
void add(int index, E ele)
boolean addAll(int index, Collection<? extends E> eles)
2、获取元素E get(int index)
List subList(int fromIndex, int toIndex) //返回从fromIndex到tolndex位置的子集合
3、获取元素索引int indexOf(Object obj) //返回obj在集合中首次出现的位置
int lastIndexOf(Object obj) //返回obj在集合中末次出现的位置
4、删除和替换元素E remove(int index)
E set(int index, E ele) //设置指定index位置的元素为ele
List的实现类
1.ArrayList
注意事项:
1.底层是由elementData数组来实现的
2.元素增删慢,查找快,由于日常开发中使用最多的功能为查询数据、遍历数据,所以
ArrayList
是最常用的集合3.允许存储所有元素,包括null,ArrayList可以加入一个或者多个null
源码分析:
首先ArrayList有三种构造器,分别是无参构造器,一个int参数的构造器,一个Collection参数的构造器
1.当调用无参构造器时,初始elementData容量为0
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
2.调用int参数的构造器时,elementData的容量为int值的大小
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
3. 调用Collection参数的构造器时,会将传入的c转为数组赋值给elementData,并且将size设置为c的长度
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
在添加元素时,会调用ensureCapacityInternal这个方法,确定是否需要扩容
public boolean add(E e) {
ensureCapacityInternal(size + 1);
elementData[size++] = e;
return true;
}
如果是第一次添加小于10个数据,elementData 扩容为默认值(10),然后进行数据添加,之后再添加,如果添加后长度没有超出数组最大限度,则直接添加,如果超出了,就要进行扩容,每次扩容都是创建一个长度为原数组1.5倍的新数组,让elementData指向新数组,然后再添加。
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {
// 检测数据是否为空
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
// 从默认值(10)与传入参数中选择最大的数进行返回
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
private void ensureExplicitCapacity(int minCapacity) {
// 更新数自增
modCount++;
// 如果已经无法添加元素了(数组已满),就进行扩容
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
// 默认扩容1.5倍
int newCapacity = oldCapacity + (oldCapacity >> 1);
// 最大值溢出处理
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
// 没有溢出就为int最大值
newCapacity = hugeCapacity(minCapacity);
// 转移数据
elementData = Arrays.copyOf(elementData, newCapacity);
}
2.LinkedList
注意事项:
1.LinkedList底层是一个双向链表,使用Node包装了指针的信息与数据的内容
2.理论只受限于内存大小,所以不需要扩容操作
// 指针头,表示第一个节点
transient Node<E> first;
// 指针尾,表示最后一个节点
transient Node<E> last;
// node节点包装
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
public LinkedList() {
}
public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}
在调用有参构造器时,会调用addAll方法,addAll方法的具体实现如图
假设LinkedList是有元素的。
那么经过addAll方法后改变它的结构
原来的LinkedList没有元素时
在添加新元素时,用add()方法
public boolean add(E e) {
linkLast(e);
return true;
}
void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
// last为空说明原本链表没有元素,那么新增的元素就是第一个也是最后一个
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
3.Vector
1.Vector底层也是一个对象数组,protected objectl] elementData;
2. Vector 是线程同步的,即线程安全,Vector类的操作方法带有synchronized