概述
此文章属于个人看过底层源码以后、自己手写实现的学习文章、如有不对或者考虑的不够具体的方面、请多指教、相互学习、谢谢
ArrayList源码
1、默认的无参构造方法、默认数组大小是10、如果指定了数组大小、就使用指定了的大小、(注意如果指定的大小是小于0的话、就抛出个异常)
2、添加元素、如果达到了目前的定义的初始长度、比如10、就需要扩容、还有元素数+1
3、扩容的时候、如果自定义了初始大小、并且是0或者是1、就会在Arrays.copyOf( data, data.length+(data.length>>1))、0>>1还是0、还有1>>1还是1 然后这个在放元素的时候就会报错、可以判断下、然后不用右移、直接给个任意的大小不是0就行、
4、根据索引添加元素的时候、索引是否越界问题>size 还有小于0、抛异常、然后就是把元素从索引位置右移一个、还有扩容问题
5、根据索引查找元素、
6、看list中是否包含xxx元素、
7、获取指定下标元素、
8、移除指定位置元素、
class ArrList {
// 用于存储数据
private Object[] data;
// 记录元素个数
private int size = 0;
public ArrList() {
this.data = new Object[10];
}
public ArrList(int initialCapacity) {
if (initialCapacity < 0)
throw new IllegalArgumentException();
this.data = new Object[initialCapacity];
}
// 添加元素
public void add(Object o) {
// 判断是否需要扩容
if (size >= data.length)
grow();
data[size] = o;
size++;
}
// 用于扩容
private void grow() {
if (data.length <= 1)
data = Arrays.copyOf(data, data.length + 1);
else
data = Arrays.copyOf(data, data.length + (data.length >> 1));
}
// 插入
public void add(int index, Object o) {
// 判断下标越界
if (index > size || index < 0)
throw new IndexOutOfBoundsException("Index:" + index + ", Size:" + size);
// 判断扩容
if (size >= data.length)
grow();
// for(int i = size - 1; i >= index; i--){
// data[i + 1] = data[i];
// }
System.arraycopy(data, index, data, index + 1, size - index);
data[index] = o;
size++;
}
// 清空列表
public void clear() {
data = new Object[10];
size = 0;
}
// 判断是否包含指定的元素
public boolean contains(Object o) {
return indexOf(o) != -1;
}
// 判断下标是否越界
private void outOfBounds(int index) {
if (index >= size || index < 0)
throw new IndexOutOfBoundsException("Index:" + index + ", Size:" + size);
}
// 获取指定下标上的元素
public Object get(int index) {
outOfBounds(index);
return data[index];
}
// 获取指定元素第一个出现的下标
// indexOf(null)
public int indexOf(Object o) {
// 为了防止出现空指针异常,需要判断参数是否位null
// 如果o为null并且data[i]也为null
for (int i = 0; i < size; i++) {
if (o == data[i] || o != null && o.equals(data[i])) {
return i;
}
}
return -1;
}
public boolean isEmpty() {
return size <= 0;
}
// 获取指定的元素最后一次出现的位置
public int lastIndexOf(Object o) {
for (int i = size - 1; i >= 0; i--) {
if (o == data[i] || o != null && o.equals(data[i]))
return i;
}
return -1;
}
// 移除指定下标上的元素
public void remove(int index) {
outOfBounds(index);
// for (int i = index; i < size - 1; i++) {
// data[i] = data[i + 1];
// }
System.arraycopy(data, index + 1, data, index, size - (index + 1));
size--;
}
// 移除指定的元素
public void remove(Object o) {
// 找到这个元素第一次出现的位置
int index = indexOf(o);
// 判断是否找到了这个元素
if (index != -1)
remove(index);
}
// 替换
public void set(int index, Object o) {
outOfBounds(index);
data[index] = o;
}
public int size() {
return size;
}
// 截取子列表
public ArrList subList(int fromIndex, int toIndex) {
if (fromIndex < 0 || toIndex < 0 || toIndex > size)
throw new IllegalArgumentException();
int size = toIndex - fromIndex;
if (size < 0)
throw new IllegalArgumentException();
ArrList sub = new ArrList(size);
System.arraycopy(data, fromIndex, sub.data, 0, size);
sub.size = size;
return sub;
}
public Object[] toArray() {
Object[] newArr = new Object[size];
System.arraycopy(data, 0, newArr, 0, size);
return newArr;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("[");
for (int i = 0; i < size; i++) {
sb.append(data[i]).append(", ");
}
String str = sb.toString();
if (size > 0)
str = str.substring(0, str.length() - 2);
return str += "]";
}
}
ArrayList源码
class LinkList {
private int size = 0;
private Node first;
private Node last;
// 添加元素
public void add(Object o) {
// 创建一个新的节点存储元素
Node node = new Node(null, o, null);
// 判断是否是第一个节点
if (size == 0) {
// 将头节点指向新节点
this.first = node;
} else {
// 将原来尾节点的下一位指向新节点
this.last.next = node;
// 将新节点的上一位指向原来的尾节点
node.prev = last;
}
// 将尾节点挪到新节点上
this.last = node;
size++;
}
// 插入
public void add(int index, Object o) {
// 判断下标是否越界
if (index > size || index < 0)
throw new IndexOutOfBoundsException("Index:" + index + ", Size:" + size);
// 插在尾部相当于添加
if (index == size) {
add(o);
return;
}
Node node = new Node(null, o, null);
// 插在头部
if (index == 0) {
// 新节点的下一位是原来的头节点
node.next = this.first;
// 原来的头节点的上一位是新的节点
this.first.prev = node;
// 将头结点挪到新节点上
this.first = node;
} else {
// 找到指定下标对应的节点
Node no = getNode(index);
// 原节点的上一位的下一个节点是新节点
no.prev.next = node;
// 新节点的上一位是原节点的上一位
node.prev = no.prev;
// 新节点的下一位是原节点
node.next = no;
// 原节点的上一位是新节点
no.prev = node;
}
size++;
}
private Node getNode(int index) {
Node node = this.first;
for (int i = 0; i < index; i++) {
node = node.next;
}
return node;
}
public void clear() {
this.first = this.last = null;
size = 0;
}
public boolean contains(Object o) {
return indexOf(o) != -1;
}
// 判断下标是否越界
private void outOfBounds(int index) {
if (index >= size || index < 0)
throw new IndexOutOfBoundsException("Index:" + index + ", Size:" + size);
}
public Object get(int index) {
outOfBounds(index);
return getNode(index).data;
}
public int indexOf(Object o) {
// 指向头节点
Node node = this.first;
int index = 0;
// 判断该节点是否为空
while (node != null) {
// 判断该节点的数据和指定的数据是否相等
if (o == node.data || o != null && o.equals(node.data)) {
return index;
}
// 如果该节点的数据和指定的数据不相等,则挪到下一个节点上
node = node.next;
index++;
}
return -1;
}
public boolean isEmpty() {
return size <= 0;
}
public int lastIndexOf(Object o) {
Node node = this.last;
int index = size - 1;
while (node != null) {
if (o == node.data || o != null && o.equals(node.data))
return index;
node = node.prev;
index--;
}
return -1;
}
public void remove(int index) {
outOfBounds(index);
// 判断是否是只有一个节点
if (size == 1) {
this.first = this.last = null;
} else {
// 是否是头节点
if (index == 0) {
this.first = this.first.next;
this.first.prev = null;
} else if (index == size - 1) {
this.last = this.last.prev;
this.last.next = null;
} else {
// 找到这个节点
Node node = this.getNode(index);
node.prev.next = node.next;
node.next.prev = node.prev;
}
}
size--;
}
public void remove(Object o) {
int index = indexOf(o);
if (index != -1)
remove(index);
}
public void set(int index, Object o) {
outOfBounds(index);
getNode(index).data = o;
}
public int size() {
return size;
}
public LinkList subList(int fromIndex, int toIndex) {
if (fromIndex < 0 || toIndex < 0 || toIndex > size || toIndex < fromIndex)
throw new IllegalArgumentException();
int size = toIndex - fromIndex;
LinkList sub = new LinkList();
Node node = this.getNode(fromIndex);
for (int i = 0; i < size; i++) {
sub.add(node.data);
node = node.next;
}
return sub;
}
public Object[] toArray() {
Object[] os = new Object[size];
int i = 0;
Node node = this.first;
while (node != null) {
os[i] = node.data;
node = node.next;
i++;
}
return os;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("[");
Node node = this.first;
while (node != null) {
sb.append(node.data).append(", ");
node = node.next;
}
String str = sb.toString();
if (size != 0)
str = str.substring(0, str.length() - 2);
return str += "]";
}
private class Node {
Node prev;
Object data;
Node next;
public Node(Node prev, Object data, Node next) {
super();
this.prev = prev;
this.data = data;
this.next = next;
}
}
}