- ArrayList
- 查看了数据结构,简单的实现了一下ArrayList,主要注意的就是add 和 remove ,当然更多细节肯定没有做的,比如源码里有个关键字段modCount。。。
public void add(int index, T t) {
checkIndex(index);
//当数组满了就增加容量
if (mItems.length == size()){
ensureCapacity(size() * 2 + 1);
}
//然后进行插入操作
for (int i = theSize; i > index ; i-- ) {
mItems[i] = mItems[i - 1];
}
mItems[index] = t;
theSize++;
}
public T remove(int index){
checkIndex(index);
Object mItem = mItems[index];
//取出数据后在进行排列
for (int i = index; i < size() - 1 ; i++) {
mItems[i] = mItems[i + 1];
}
theSize -- ;
return (T) mItem;
}
public T get(int indx){
return (T) mItems[indx];
}
public T set(int inx , T t){
if (inx < 0 || inx > theSize){
throw new IndexOutOfBoundsException();
}
Object mItem = mItems[inx];
mItems[inx] = t;
return (T) mItem;
}
查看add remove 就可以知道为什么增删会耗时了,因为增删操作会将后面的数据全部进行移动!
所以就增加的耗时的操作时间
然而 get set 却 只是通过数组的下标来直接获取数值- LinkedList
- 简单实现一下LinkedList,主要就是节点 Node , 然后就是add(t) , addBefore (int ,t),get(int) 这3个方法的细节
//节点指针
private static class Node<T>{
//指向上一个node
private Node<T> prev;
//指向下一个node
private Node<T> next;
//数据
private T t;
public Node(Node<T> prev, Node<T> next, T t) {
this.prev = prev;
this.next = next;
this.t = t;
}
}
//标记
private Node<T> startMarker;
private Node<T> endMarker;
/**
* 添加数据到某条数据的前面
*/
public void add(T t){
addBefore(size() , t);
}
public void addBefore(int index ,T t){
if (index == size()){
Node<T> newNode = new Node<>(endMarker.prev, endMarker, t);
newNode.prev.next = newNode;
endMarker.prev = newNode;
}else {
Node<T> node = node(index);
Node<T> newNode = new Node<>(node.prev, node, t);
newNode.prev.next = newNode;
node.prev = newNode ;
}
theSize ++ ;
modCount ++ ;
}/**
* 移除某条数据
*/
public T remove(int index) {
Node<T> p = node(index);
return toRemove(p);
}
public T remove() {
Node<T> prev = endMarker.prev;
return toRemove(prev);
}
private T toRemove(Node<T> p) {
p.prev.next = p.next;
p.next.prev = p.prev;
theSize--;
modCount++;
return p.t;
}/**
* 通过下标 index 获取某条数据
*/
public T get(int index){
return node(index).t;
}
/**
*这里通过下标来进行 遍历 获取 下标对应的节点信息
*/
Node<T> node(int index){
Node<T> node = null;
//小于一半的size 就从开始的地方遍历 , 否则了就从尾部开始遍历 , 遍历完就是最后得到的数据
if (index < size()/2 ){
node = startMarker.next;
for (int i = 0; i < index; i++) {
node = node.next;
}
}else {
node = endMarker.prev;
for (int i = size()-1 ; i > index; i-- ) {
node = node.prev;
}
}
return node;
} 其实 remove方法 和 add 方法很简单,只不过是吧当前数据对应节点的上一个、下一个的引用进行
更改就行,不需要在改动剩下的数据;
但是addBefore(index , t) 和 get(index) 、 remove(index)方法却需要通过 下标 来获取对应的节点,
这就需要通过node(index)方法来进行遍历的获取 ---> 这就是耗时操作的原因!!!
- 这里附上LinkedList的add remove图解
add
remove