左侧由Collection而来的集合类属于存储很多单个数据
右侧由map而来的则存储键值对
collection为list和set的父接口,他要求了这些集合类应该实现哪些内容
集合层次结构中的根界面 。 集合表示一组被称为其元素的对象。 一些集合允许重复元素,而其他集合不允许。 有些被命令和其他无序。 JDK不提供此接口的任何直接实现:它提供了更具体的子接口的实现,如Set和List 。 该界面通常用于传递集合,并在需要最大的通用性的情况下对其进行操作。
boolean add(E e) 增加元素
clear() 从此集合中删除所有元素
remove(object o) 从该集合中删除指定元素的单个实例
iterator() 返回此集合中的元素的迭代器。
size() 返回此集合中的元素数。
contains(object o) 如果此集合包含指定的元素,则返回 true 。
equals(object o) 将指定的对象与此集合进行比较以获得相等性。
isEmpty() 如果此集合不包含元素,则返回 true 。
list继承了Collection接口并在原接口上做了增强
list常用方法
boolean add(E e) 将指定的元素追加到此列表的末尾(可选操作)。
void add(int index, E element) 将指定的元素插入此列表中的指定位置(可选操作)。
E get(int index) 返回此列表中指定位置的元素。
set(int index, E element) 用指定的元素(可选操作)替换此列表中指定位置的元素。
boolean remove(Object o) 从列表中删除指定元素的第一个出现(如果存在)(可选操作)。
E remove(int index) 删除该列表中指定位置的元素(可选操作)。
可以注意到最后两个remove的操作都只传递一个参数
那么我们使用list.remove(2)时究竟是删除索引为2的参数还是内容为2的参数呢
使用如下程序进行测试:
public static void main(String[] args) {
List list=new ArrayList();
list.add(12);
list.add(99);
list.add(69);
list.add(2);
list.remove(2);
System.out.println(list);
}
结果:
[12, 99, 2]
由此得知是删除了索引为2的数据
那么我们想删除2这个数据呢
public static void main(String[] args) {
List list=new ArrayList();
list.add(12);
list.add(99);
list.add(69);
list.add(2);
list.remove(new Integer(2));
System.out.println(list);
}
我们是需要这样操作即可
追究其原因,是因为Collection中存储的对象是包装类,而2是基本数据类型,所以只需要将2变为包装类就可以删除2这个数据了
但这点不适用于add时,因为add会进行自动装箱操作而调用remove时则不会进行自动装箱
arraylist本质为一个数组以及一个int的组合
在1.7中构造器默认开辟10个长度的数组以供使用
// 添加元素
public boolean add(E e) {
// 扩容
ensureCapacityInternal(size + 1);
//将数组第size位置添加为该元素,并扩充size
elementData[size++] = e;
//返回真
return true;
}
其他代码都很好理解,主要是第一句ensureCapacityInternal是个什么函数呢,我们点击去看一下
ensureCapacityInternal(int minCapacity)
这里可以看见此函数做出了一个判断
如果目前长度不够用了,就调用grow函数并将其需要的最小容量传过去
那么grow里又写了什么呢,继续点进去看一下
分析一下
这个函数第一步先预估了一下新数组的长度
使newcapacity等于了旧数组的1.5倍
下一步判断,如果新的长度仍不能满足要求
使新长度等于最低的长度要求
关于下一步目前没有安装1.7版本的JDK所以没能理解
最后一步
arraycopyOf(T[] original, int newLength) 复制指定的数组,用空值截断或填充(如有必要),以便复制具有指定的长度。
创建新的数组并将原存放数据的数组指定回去
这里与jdk1.7版本中有较大差异
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
public ArrayList() {
//将主要用于存储数据的数组指向了一个空数组
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
将容量的初始化交给了别的函数比如add
个人理解是为了减少空间的浪费
// 添加元素
public boolean add(E e) {
// 扩容
ensureCapacityInternal(size + 1);
//将数组第size位置添加为该元素,并扩充size
elementData[size++] = e;
//返回真
return true;
}
截止目前 add操作和1.7中几乎一样,下一步开始变的不太一样
ensureCapacityInternal(int minCapacity)private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
这里又调用了两个未知的函数
我们先选择calculateCapacity点进去看一下
private static int calculateCapacity(Object[] elementData, int minCapacity) {
//当前数据数组是否为原空数组
//如果是则将 最小需要值与DEFAULT_CAPACITY比较得到较大的一个将其返回
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
//若不为空则返回最小的需要值
return minCapacity;
}
我们再看会上一层,它将本层函数得到的值传给了ensureExplicitCapacity()
ensureExplicitCapacity(int minCapacity)此函数则和jdk1.7中的ensureCapacityInternal(int minCapacity)一致
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)//比较传来的参数和现在存储数据数组的长度
grow(minCapacity);//扩容
}
grow(int minCapacity)
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
//旧的容量为当前数组长度
int newCapacity = oldCapacity + (oldCapacity >> 1);
//新的容量为当前数组长度的1.5倍
if (newCapacity - minCapacity < 0)
//判断当前的容量是否不足于需要的最小容量
newCapacity = minCapacity;
//如果不足,则新容量为当前需要的最小容量
if (newCapacity - MAX_ARRAY_SIZE > 0)
//判断现在的新容量是否大于int的最大容量-8
newCapacity = hugeCapacity(minCapacity);
//如果大于,则进去hugeCapacity方法返回新的容量
elementData = Arrays.copyOf(elementData, newCapacity);
//按照最新容量复制数组,实现扩容
}
分析一下
这个函数第一步先预估了一下新数组的长度
使newcapacity等于了旧数组的1.5倍
下一步判断,如果新的长度仍不能满足要求
使新长度等于最低的长度要求
下一步 判断现在的新容量是否大于int的最大容量-8
//如果大于,则进去hugeCapacity方法返回新的容量
最后一步
arraycopyOf(T[] original, int newLength) 复制指定的数组,用空值截断或填充(如有必要),以便复制具有指定的长度。
创建新的数组并将原存放数据的数组指定回去
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0)
// 如果当前需要的最小容量小于0
throw new OutOfMemoryError();
//抛出内存溢出的错误
return (minCapacity > MAX_ARRAY_SIZE) ?
//返回当前最小容量与MAX_ARRAY_SIZE谁大
Integer.MAX_VALUE :
//最小容量大,返回Integer.MAX_VALUE ,即2147483647
MAX_ARRAY_SIZE;
//否则返回MAX_ARRAY_SIZE,即2147483639
}
vector
同样实现了list接口,且底层同样是采用数组扩容机制,源码也与arraylist接近,不过扩容机制更为激进
区别:
vector是线程安全的,效率低
arraylist则是不安全的,效率高



