ArrayList底层基于数组,数组在内存上是连续分配的地址空间,是对数组的升级,长度是动态的。
自定义ArrayList:
class MyArrayList<E>{
private E[] elements;//存放元素的容器
private int size; //实际的元素个数
private final static int defaultCapacity = 5; //默认的初始化参数
public MyArrayList(){
this(defaultCapacity);
}
public MyArrayList(int capacity){
elements = (E[])new Object[capacity];
}
public void add(E value){
//判断是否需要扩容
if(size == elements.length){
//扩容
this.elements = Arrays.copyOf(this.elements, 2*elements.length);
}
//插入元素到数组尾
elements[size++] = value;
}
public boolean remove(E value){
if(size == 0){
return false;
}
for(int i=0; i<size; i++){
if(value.equals(this.elements[i])){
//i位置是所要删除的元素
System.arraycopy(this.elements, i+1, this.elements, i, size-1-i);
this.elements[--size] = null;
return true;
}
}
return false;
}
public boolean set(int index, E value){
try{
checkIndex(index);
elements[index] = value;
return true;
} catch (UnsupportedOperationException e){
System.out.println(e.getMessage());
return false;
}
}
public void checkIndex(int index){
if(index < 0 || index >= elements.length){
throw new UnsupportedOperationException("the index is illegal");
}
}
public E get(int index){
try{
checkIndex(index);
return elements[index];
}catch (UnsupportedOperationException e){
System.out.println(e.getMessage());
return null;
}
}
public boolean contains(E value){
if(size == 0){
return false;
}
for(int i=0; i<size; i++){
if(this.elements[i].equals(value)){
return true;
}
}
return false;
}
public int size(){
return this.size;
}
public boolean isEmpty(){
return this.size == 0;
}
public String toString(){
StringBuilder strs = new StringBuilder();
for(int i=0; i<size; i++){
strs.append(elements[i]+" ");
}
return strs.toString();
}
public class TestDemo1 {
public static void main(String[] args) {
MyArrayList<String> list = new MyArrayList<>();
list.add("1");
list.add("2");
list.add("3");
list.add("4");
list.add("5");
list.add("6");
list.add("7");
System.out.println(list.toString());
list.remove("6");
list.remove("10");
System.out.println(list.toString());
list.set(0, "100");
list.set(5, "tulun");
System.out.println(list.toString());
List<String> list1= new ArrayList<>();
list1.add("123");
list1.add("456");
list1.remove("123");
System.out.println(list1.size());
String[] s = (String[])list1.toArray();
list1.set(0, "tulun");
}
}
LinkedList底层基于双向链表实现,它和基于数组的list相比,在内存中空间是不连续的,可以作为list使用,也可以作为queue使用。
自定义LinkedList:
class MyLinkedList<E>{
private int size; //链表的元素个数
private Node<E> first; //指向链表的第一个元素
private Node<E> last; //指向链表的最后一个元素
class Node<E>{
private E data;
private Node<E> prev;
private Node<E> next;
public Node(E data, Node<E> prev, Node<E> next){
this.data = data;
this.prev = prev;
this.next = next;
}
}
public void add(E value){
//尾插法
//考虑链表为空和链表不为空两种情况
Node<E> newNode = new Node<>(value, last, null);
if(last == null){
first = newNode;
}else{
last.next = newNode;
}
last = newNode;
size++;
}
public void add(int index, E value){
//确定index执行的节点
if(index < 0 || index > size){
return;
}
if(index == size){
//尾插法
add(value);
}else{
Node<E> succ = findNodeByIndex(index);
Node<E> succPrev = succ.prev;
Node<E> newNode = new Node(value, succPrev, succ);
succ.prev = newNode;
if(succPrev == null){
//原先链表只有一个节点
first = newNode;
}else{
succPrev.next = newNode;
}
}
}
public Node<E> findNodeByIndex(int index){
Node<E> tmp = first;
for(int i=0; i<index; i++){
tmp = tmp.next;
}
return tmp;
}
public boolean remove(E value){
//删除元素所在的节点
Node<E> succ = findNodeByValue(value);
if(succ == null){
return false;
}
Node<E> succPrev = succ.prev;
Node<E> succNext = succ.next;
if(succPrev == null){
//所要删除的是第一个节点
first = succNext;
}else{
succPrev.next = succNext;
succ.prev = null;
}
if(succNext == null){
//所要删除的是最后一个节点
last = succPrev;
}else{
succNext.prev = succPrev;
succ.next = null;
}
succ.data = null;//方便垃圾回收
size--;
return true;
}
public Node<E> findNodeByValue(E value){
//返回value所对应的第一个节点
for(Node<E> tmp=first; tmp != null; tmp=tmp.next){
if(value.equals(tmp.data)){
return tmp;
}
}
return null;
}
public E set(int index, E newValue){
if(index < 0 || index >= size){
return null;
}
Node<E> succ = findNodeByIndex(index);
E oldValue = succ.data;
succ.data = newValue;
return oldValue;
}
public E get(int index){
if(index < 0 || index >= size){
return null;
}
return findNodeByIndex(index).data;
}
@Override
public String toString(){
StringBuilder strs = new StringBuilder();
for(Node<E> tmp=first; tmp!=null; tmp=tmp.next){
strs.append(tmp.data+" ");
}
return strs.toString();
}
}
public class TestDemo4 {
public static void main(String[] args) {
LinkedList<Integer> list = new LinkedList<>();
list.add(1);
list.add(10);
list.add(100);
list.addLast(2);
list.removeFirst();
list.remove(1);
System.out.println(list.get(1));
list.set(1, 1000);
for(Integer i: list){
System.out.println(i);
}
Iterator<Integer> itr = list.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
}
Vector和ArrayList的区别和联系
相同点:Vector是在1.5之前使用的,集合框架库之后很少用。两者都是基于数组实现的,继承关系,实现的接口都是一样的。
区别:ArrayList1.5倍扩容,Vector2倍扩容.
构造函数稍微不同
线程安全不同,Vector是线程安全的
效率不同,Vector是同步的,所以效率会低于ArrayList。
LinkedList和ArrayList的区别和联系
区别:1.LinkedList底层是基于双向链表,ArrayList底层是基于数组实现的。
2.ArrayList访问效率高于LinkedList,因为数组访问效率高,双向链表还有前驱后驱指向,访问麻烦。
3.对于增删方法,LinkedList访问效率高于ArrayList,数组要一个一个按顺序删,而链表可以用指向直接断开链接。
联系ArrayList和LinkedList都是List接口的实现类,这两个类都是对List进行操作。List接口里定义了它们必须要实现的方法,比如add(E)、get(int)、remove(int)、set(E)等基本的List操作,然后这两个类就按照它们自己的方法来实现这些List的基本操作。