一、ArrayList和LinkedList区别
ArrayList:底层是基于动态数组
根据数组下标访问数组元素的效率最高,向尾部添加元素效率高。
删除数组中元素以及数组中添加数据的效率低,因为要移动数组。(最坏情况下删除第一个元素,要移动第2~n-1个元素都要向前移动一位。
LinkedList:基于链表的动态数组
数据删除添加效率高,只要改变指针指向即可,但是访问数据的平均效率低,需要对链表进行遍历。
总结:对于增加(add)和删除(remove)操作,LinkedList优于ArrayList,因为ArrayList要移动数组。
对于随机访问get和set,ArrayList优于Linked List,因为LinkedList要移动数组。
二、ArrayList类中的主要属性和内部类
1.实现ArrayList的相关接口List
public interface List extends Iterable{
boolean add(Integer e);
void add(int index,Integer e);
//根据下标删除
Integer remove(int index);
//删除遇到第一个
boolean remove(Integer e);
Integer get(int index);
Integer set(int index,Integer e);
int size();
void clear();
boolean isEmpty();
boolean contains(Integer e);
int indexOf(Integer e);
int lastIndexOf(Integer e);
2.ArrayList类中的主要属性及构造方法
package List;
import java.lang.reflect.Array;
import java.util.Arrays;
public class ArrayList implements List {
private int[] array;
private int size;
//无参数构造方法
public ArrayList(){
array=new int[10];
size=0;
}
//有参数构造方法
public ArrayList(List other){
array=new int[other.size()];
for(int i=0;i<other.size();i++){
array[i]=other.get(i);
}
size=other.size();
}
3.**添加(Add)**元素的方法
public boolean add(Integer e) {
//扩容
if(array.length==size){
ensureCapacity(array.length*2);
}
//相当于尾插
array[size++]=e;
return true;
}
在指定位置index添加e
public void add(int index, Integer e) {
//合法性校验
if(index<0||index>size){
throw new IndexOutOfBoundsException("不合法的下标:"+index);
}
//扩容2倍
if(array.length==size){
ensureCapacity(array.length*2);
}
//循环实现的效果是一样的
// for(int i=size;i>index;i--){
// array[i]=array[i-1];
// }
for(int i=size-1;i>=size;i--){
array[i+1]=array[i];
}
array[index]=e;
size++;
}
4.查找相关方法
public Integer get(int index) {
if(index<0||index>=size){
throw new IndexOutOfBoundsException("下标不合法"+index);
}
return array[index];
}
5.插入相关方法
public Integer set(int index, Integer e) {
if(index<0||index>=size){
throw new IndexOutOfBoundsException("下标不合法"+index);
}
Integer old=array[index];
array[index]=e;
return old;
}
6.删除相关方法
public Integer remove(int index) {
if(index<0||index>=size){
throw new IndexOutOfBoundsException("下标不合法"+index);
}
int e=array[index];
//从前往后删除
//[index+1,size-1)的元素搬移到[index,size-2]的位置上
for(int i=index;i<size;i++){
array[i]=array[i+1];
}
size--;
return e;
}
public boolean remove(Integer e) {
// for(int i=0;i<size;i++){
// if(array[i]==e){
// remove(i);
// return true;
// }
// }
// return false;
int index=indexOf(e);
if(index!=-1){
remove(index);
return true;
}else{
return false;
}
}
7.重写ArrayList的toString方法
扫描二维码关注公众号,回复:
12764852 查看本文章
public String toString() {
StringBuilder sb=new StringBuilder("[");
for(int i=0;i<size;i++){
sb.append(array[i]);
if(i!=size-1){
sb.append(",");
}
}
sb.append("]");
return sb.toString();
}
8.其他方法(扩容)(Iterator)
public void ensureCapacity(int capacity){
//检查是否需要搬家
if(this.array.length>=capacity){
return;
}
int[] newArray=new int[capacity];
//从array数组中搬到newArray数组中
for(int i=0;i<size;i++){
newArray[i]=this.array[i];
}
//不再关联老的Array
this.array=newArray;
}
三、LinkedList类中的主要属性和内部类
1.定义Node节点
public class Node {
public Node prev;
public Node next;
public Integer element;
public Node(Integer element){
this.element=element;
}
}
- add相关方法
public boolean add(Integer e) {
Node newNode=new Node(e);
if(size==0){
this.head=this.last=newNode;
}else{
this.last.next=newNode;
newNode.prev=this.last;
this.last=newNode;
}
this.size++;
return true;
}
在指定位置index添加e:
public void add(int index, Integer e) {
if(index<0||index>size){
throw new IndexOutOfBoundsException("下标越界"+index);
}
if(index==size){
//尾插
add(e);
}else if(index==0){
//头插
Node newNode=new Node(e);//把值装入结点中
newNode.next.prev=newNode;
this.head=newNode;
size++;
}else{
//其他情况
//找到Index-1所在的位置,进行结点的插入
Node prev;
if(index-1<size/2){
prev=head;
for(int i=0;i<index-1;i++){
prev=prev.next;
}
}else{
prev=last;
for(int i=0;i<size-index;i++){
prev=prev.prev;
}
}
//走到这里,prev指向index-1位置的下标
Node next=prev.next;
Node newNode=new Node(e);
newNode.prev=prev;
newNode.next=next;
prev.next=newNode;
next.prev=newNode;
size++;
}
}
3.remove相关方法
public Integer remove(int index) {
if(index<0||index>=size){
throw new IndexOutOfBoundsException("下标越界"+index);
}
//走到这里,下标一定是>0的
Integer v;
if(index==0){
v=head.element;
this.head=this.head.next;
this.head.prev=null;
size--;
if(size==0){
last=null;
}
}else if(index==size-1){
v=last.element;
this.last=this.last.prev;
this.last.next=null;
size--;
if(size==0){
head=null;
}
}else{
Node prev;
if(index-1<size/2){
prev=head;
for(int i=0;i<index-1;i++){
prev=prev.next;
}
}else {
prev=last;
for(int i=0;i<size-index;i++){
prev=prev.prev;
}
}
Node toRemove=prev.next;
v=toRemove.element;
prev.next=toRemove.next;
toRemove.next.prev=prev;
size--;
}
return v;
}
4.其他方法
public boolean isEmpty() {
return size==0;
}
public boolean contains(Integer e) {
return indexOf(e)!=-1;
}
public int indexOf(Integer e) {
int i=0;
for(Node cur=head;cur!=null;cur=cur.next,i++){
if(cur.element.equals(e)){
return i;
}
}
return -1;
}
public int lastIndexOf(Integer e) {
int i=size-1;
for(Node cur=last;cur!=null;cur=cur.prev,i--){
if(cur.element.equals(e)){
return i;
}
}
return -1;
}
public Iterator iterator() {
return new LinkedListIterator(this);
}