对象比较
理论: 两个对象是否是同一个对象: == equals() 都是在比较地址码是否一样,
在实际开发中: 两个对象是否是同一个对象: 1. 如果地址码是否一样, 2. 两个对象的属性值是否一样
对自定义的类类型, 重写Object的equlas()方法, 重写hashCode()
set集合可以去重,但是set集合不能通过for循环遍历,没有下标
Set集合判断一个对象是否相等
判断两个对象的hashCode是否一样, 如果hashCode一样, 进行equlas()判断
如果hashCode一样,equals()返回true, 表示是同一个对象
如果hashCode不一样, 不会判断eqauls() , 不是同一个对象
如果hashCode一样,但是eqauls() 返回false, 不是同一个对象
List判断两个对象是否相等
调用 对象equlas() 方法判断, 如果equals() 返回true, 表示同一个对象, 与hashCode无关
ArrayList: 数组结构, 查询效率高, 修改(插入元素,删除元素)效率低
LinkedList: 双向链表结构: 查询效率低, 修改效率高
ArrayList
public void add(int index, E element) {
rangeCheckForAdd(index);//检查下标是否越界
ensureCapacityInternal(size + 1); // Increments modCount!! 数组扩容
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
//数组复制,相当于增加了。index的位置空了
//arraycopy(当前数组,起始复制下标,目标数组,起始下标,复制长度)
elementData[index] = element;
size++;
}
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
add() 添加元素的源码:
public ArrayList() {
//elementData 是空数组, 长度为0
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; //{}
}
list.add("abc");
//10个元素
public boolean add(E e) {
//确定所需容量: 1
ensureCapacityInternal(size + 1); // Increments modCount!!
//size=0 size=size+1
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
//elementData: {} minCapacity: 1
private static int calculateCapacity(Object[] elementData, int minCapacity) {
//第一次添加
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
//max(10,1) 返回10
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
//minCapacity:10 elementData:{}
private void ensureExplicitCapacity(int minCapacity) {
modCount++; //集合修改的次数: 添加,删除
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity); //进行扩容
}
//minCapacity: 10
private void grow(int minCapacity) {
// overflow-conscious code
//旧的容量
int oldCapacity = elementData.length;//0
// >> 有符号右移 正数高位补0 负数: 高位补1 >>> 无符号右移 高位补0
//<< 左移 低位补0
// oldCapacity + (oldCapacity >> 1)
//ArrayList 扩容为原来容量的1.5倍
int newCapacity = oldCapacity + (oldCapacity >> 1);//0
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity; //newCapacity:10
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// copyOf(旧数组,新长度) 把创建一个新数组, 新数组的长度: 新长度
//把旧数组的元素拷贝新数组, 把新数组返回
elementData = Arrays.copyOf(elementData, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
属性:
Object[] elementData; ArrayList元素存在elementData数组
int size; ArrayList集合的元素个数
List list = new ArrayList();
迭代器 Iterator
jdk提供了迭代器来遍历collection接口(set,list)
Iterator只能向下遍历,但是其子类ListIterator可以向上遍历
foreach的底层代码就是迭代器
如果再迭代器中使用list集合的remove,add方法就会报并发错误异常。因为迭代器一开始已经接收到了那个时刻的list对象,如果在迭代器内对list集合进行修改,那么迭代器获取到的list和修改后的list有差异,就会返回异常。(迭代器得到list集合的时候会得到modecount就是修改次数,如果之后list被修改,那么modcount不一致,就报错了。。)