数组的遍历
数组再结构上要求连续,遍历时不关心具体元素的地址,只要知道起始元素的地址以及目标元素的下标,即可快速找到目标元素。
总结:
数组结构的遍历会优于链表结构的遍历,它不需要频繁寻找地址。
ArrayList#get(i):很快
数组的插入与删除
数组的插入和删除,离不开数组的拷贝和扩容。
ArrayList被称为动态数组,原因是他会自动扩容
扩容的具体步骤是:
- ArrayList申请新的长度的数组
- 把原数组的元素拷贝到新数组
- 把新元素插入到新数组
- ArrayList#set(index, element):只是替换,不会扩容和拷贝
- ArrayList#add(e):尾部插入,只有当数组满了才扩容 ArrayList#add(index,element):
- 指定位置插入,不一定扩容,但会触发数组拷贝,尽量避免使用
重点:
- 数组的元素替换速度比链表的替换快!首先,数组查询比链表快。其次,数组元素直接赋值覆盖完成替换,而链表要先解开地址引用 add(intindex, E element)不一定会触发扩容,但几乎一定会发生拷贝
- 数组的中间插入只会移动部分元素,而头插入会移动所有元素。大家看看上面的System.arracopy()
- 当我们尾部插入时,index=size,所以length参数就是0,无需移动任何元素
ArrayList小结
• 查询
• 随便用,只有一个get(index),根据下标查询,很快
• 插入
• 尽量使用add(element),避免使用add(index, element),中间插入一定触发数组拷贝,较大概率触发扩容,扩容和拷贝不一定同时进行。是否取决于元素数量,而是否拷贝取决于本次插入位置,尾部插入无需拷贝
• 替换
• set(index, element),很快
• 删除
• 推荐循环删除时使用逆序遍历,这样可以从尾部删除,不会触发数组拷贝,禁止从头部删除