一 集合(2021-11-2)
- 动态保存任意多个元素,数据类型可以不一样。
- 提供了一系列方便操作对象的方法:add,remove,set,get(增删改查)。
- 比数组代码简洁。
1 集合框架体系
-
集合主要是两组:单列集合(集合中放的单个对象) ; 双列集合(键值对形式)。
-
Collection 接口有两个重要的子接口 List Set , 他们的实现子类都是单列集合。
-
Map 解耦的实现子类 是双列集合,存放的 K-V。
2 Collection - List
2-1 ArrayList
-
子接口(线程不安全)。
-
底层:Object 数组(适用于频繁的查找工作)。
属性:
默认初始容量 (10);
空数组(用于空实例);
默认容量数组(区分于 空数组);
保存数据的数组;
长度。
函数:
- 有参构造函数(容量):
判断:(初始容量 大于0)
- 大于0:保存数据数组 = 初始化容量 的 对象数组;
- 等于0:保存数据数组 = EMPTY_ELEMENTDATA;
- 小于0:抛出异常。
- 无参构造函数(初始容量 0)。
- add():添加单个元素。
- 无参构造 实例 list (elementData -> 默认容量空数组) 添加第一个元素流程:
add(){
ensureCapacityInternal( minCapacity(size + 1 = 1) ) {//因为第一此添加一个元素,原本的size是0。
ensureExplicitCapacity(//参数:最小容量=10
//返回 最小容量:
//(1)空数组时返回 10;
// (1-1) 第一次添加<=10,返回10; !!!只有这种情况下默认的容量10才用上了!!!
//(2)非空数组时返回 目前需要的最小容量值;
calculateCapacity(elementData (空数组), minCapacity(1)){
if (elementData(空数组) == DEFAULTCAPACITY_EMPTY_ELEMENTDATA(空数组)) { //如果 暂时存储数据的数组
return Math.max(DEFAULT_CAPACITY(10), minCapacity(1)); //是空的直接返回10就好了,为什么还要max()?:如果第一次添加的长度就超过了10,返回的是最小容量值。之后按照这个数字扩容1.5倍数,和10就没关系了;但是第一次没超过10还是要用max()的,此时不能直接返回10,之后会装不下。
}
return minCapacity; //不是空就返回 : 最小容量的这个需求。
}){//ensureExplicitCapacity{}
if (minCapacity (10) - elementData.length (0) > 0) // 最小需要容量比 现在的容量大(需求>供给)(size > capacity) 如果容量不够才扩容,够不走grow().
grow(minCapacity (10) ); {//真正进行扩容(给一个最小需求量)
//最底层的扩容机制!!!
int oldCapacity (0) = elementData.length (0) ; // 取装不下的 老容量
int newCapacity (0) = oldCapacity (0) + (oldCapacity(0) >> 1); // 新容量 = 老容量*1.5
// 空数组的话 假设扩容后的值 比 最小需求容量 小 !
if (newCapacity(0) - minCapacity(10) < 0) // 判断:如果 新容量比 最小需求容量 小!—— 放不下啦!!!
newCapacity(10) = minCapacity(10); // 新容量 = 最小需求容量
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); // 扩容使用的是Arrays.copyOf():保留原先数据。
}
}
}
新元素追加;
return true;
}
- remove:删除指定元素。
remove(index (下标){
rangeCheck(index){//检查下标
判断:如果下标 > size
抛出异常;
}
旧值 = elementData(下标); // 提取要删除的值
int numMoved (需要移动的数=删除后面的元素需要往前移动)= size - index - 1;
if (numMoved > 0) //有需要移动的
System.arraycopy(elementData, index+1, elementData, index,numMoved);
elementData[--size] = null; //最后一个空间为空
return oldValue;
}
- contains:查找元素是否存在。
return indexOf(o) { //可以查找 null
if (o == null) { // 遍历是否有空的
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else { // 不是null
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1; // 没查到
}>= 0; //查到了>=0 = 返回true
只能查找添加null的null是否存在。
- size:获取元素个数。
return size;
- isEmpty:判断是否为空。
return size == 0
- clear:清空。
我添加的null和计算机修改的不一样。
- get:查。
public E get(int index) {
rangeCheck(index);//检查下标
return elementData(index); //返回值
}
- set:改。
public E set(int index, E element) {
rangeCheck(index); //检查下标
E oldValue = elementData(index); //旧值
elementData[index] = element; //赋新值
return oldValue; //返回旧值
}
2-2 LinkedList
-
线程不安全。
-
底层:双向链表。
2-3 Vector
- 线程安全。
3 Collection - Set
-
HashSet
-
LinkedHashSet
-
TreeSet
-
Collection接口的常用方法(间接实现子类ArrayList演示):
- add
4 Map
- HashMap
- LinkedHashSet
- Hashtable
- Properties
- TreeMap