Java中Arraylist 与 LinkedList 异同

1.大概描述

ArrayList与LinkedList都是List接口的实现类,因此都实现了List的所有未实现的方法,只是实现的方式有所不同;而List接口继承了Collection接口,Collection接口又继承了Iterable接口,因此List同时拥有了Collection与Iterable接口的特性.

ArrayList:底层是数组结构,查询快,增删慢,异步,初始容量为10。
LinkedList:底层是链表结构,增删快,查询慢,异步,初始容量为0,linkedList 是一个双向链表,没有初始化大小,也没有扩容的机制,就是一直在前面或者后面新增就好,有关索引的操作可能从链表头开始遍历到链表尾部,也可能从尾部遍历到链表头部,这取决于看索引更靠近哪一端。

2.线程安全

ArrayList 和 LinkedList 都是不同步的,也就是不保证线程安全;

如果想使LinkedList变成线程安全的,可以使用如下方式:

List list=Collections.synchronizedList(new LinkedList(…));

另外还有 Collections.synchronizedMap() Collections.synchronizedSet()两个方法;

3.底层数据结构

Arraylist 底层使用的是Object数组;LinkedList 底层使用的是双向链表数据结构(JDK1.6之前为循环链表,JDK1.7取消了循环。注意双向链表和双向循环链表的区别:);

首先是ArrayList

 public class ArrayListDemo {  
  
    public static void main(String[] args) {  
          
        List<String> userlist = new ArrayList<String>();  
        userlist.add("yulon");  
        userlist.add("xiaoyun");  
        userlist.add("羽龙共舞");  
        System.out.println("使用普通for循环:");  
        for(int i=0; i<userlist.size(); i++){  
            System.out.print(userlist.get(i)+" ");  
        }  
        System.out.println();  
        System.out.println();  
        System.out.println("使用Iterator迭代器:");  
        Iterator it = userlist.iterator();  
        while(it.hasNext()){  
            System.out.print(it.next()+" ");  
        }  
        System.out.println();  
        System.out.println();  
        System.out.println("使用增强for循环:");  
          
        for(String s : userlist){  
            System.out.print(s+" ");  
        }  
    }  
} 

这里列举出了循环List列表的三种方式: 使用普通for循环,用get方法获取; 使用**Iterator迭代器,**使用next方法遍历;使用增强for循环,直接输出! 由此可见第三种方法是最方便,最简洁的!

下面是LinkedList

     public class StringStack {  
        private LinkedList<String> linkedList   
        = new LinkedList<String>();  
      
        /** 
         * 将元素加入LinkedList容器 
         * (即插入到链表的第一个位置) 
         */  
        public void push(String name){  
            linkedList.addFirst(name);  
        }  
        /** 
         * 取出堆栈中最上面的元素 
         * (即取出链表linkedList的第一个元素) 
         * @return 
         */  
        public String getTop(){  
            return linkedList.getFirst();  
        }  
        /** 
         * 取出并删除最上面的元素 
         * (即移出linkedList的第一个元素) 
         * @return 
         */  
        public String pop(){  
            return linkedList.removeFirst();  
        }  
        /** 
         * 获取元素个数 
         * @return 
         */  
        public int size(){  
            return linkedList.size();  
        }  
          
        /** 
         * 判断堆栈是否为空 
         * (即判断 linkedList是否为空) 
         * @return 
         */  
        public boolean isEmpty(){  
            return linkedList.isEmpty();  
        }  
        //测试  
        public static void main(String[] args) {  
            StringStack stack = new StringStack();  
            stack.push("yulon");  
            stack.push("xiaoyun");  
            stack.push("羽龙共舞");  
            System.out.print("第一个元素是:\t");  
            System.out.println(stack.getTop());  
            System.out.println();  
            System.out.println("全部元素:");  
            while(!stack.isEmpty()){  
                System.out.println("\t"+stack.pop());  
            }  
        }  
    }  

LinkedList的特有方法(本身定义的方法)如:addFirst()、addLast()、getFirst()、getLast()、removeFirst()、removeLast()等

4.插入和删除是否受元素位置的影响

① ArrayList 采用数组存储,所以插入和删除元素的时间复杂度受元素位置的影响。 比如:执行add(E e) 方法的时候, ArrayList 会默认在将指定的元素追加到此列表的末尾,这种情况时间复杂度就是O(1)。但是如果要在指定位置 i 插入和删除元素的话(add(int index, E element) )时间复杂度就为 O(n-i)。因为在进行上述操作的时候集合中第 i 和第 i 个元素之后的(n-i)个元素都要执行向后位/向前移一位的操作。

② LinkedList 采用链表存储,所以插入,删除元素时间复杂度不受元素位置的影响,都是近似 O(1)而数组为近似 O(n)。

5. 是否支持快速随机访问

LinkedList 不支持高效的随机元素访问,而 ArrayList 支持。快速随机访问就是通
过元素的序号快速获取元素对象(对应于get(int index) 方法)。

6. 内存占用空间

ArrayList的空 间浪费主要体现在在list列表的结尾会预留一定的容量空间,而LinkedList的空间花费则体现在它的每一个元素都需要消耗比ArrayList更多的空间(因为要存放直接后继和直接前驱以及数据)。

另外

ArrayList 实现了 RandomAccess 接口, 而 LinkedList 没有实现。为什么呢?我觉得还是和底层数据结构有关!ArrayList 底层是数组,而 LinkedList 底层是链表。数组天然支持随机访问,时间复杂度为 O(1),所以称为快速随机访问。

链表需要遍历到特定位置才能访问特定位置的元素,时间复杂度为 O(n),所以不支持快速随机访问。,ArrayList 实现了 RandomAccess 接口,就表明了他具有快速随机访问功能。 RandomAccess 接口只是标识,并不是说 ArrayList 实现 RandomAccess 接口才具有快速随机访问功能的!

参考1:https://blog.csdn.net/bjzhuhehe/article/details/72230559
参考2:https://blog.csdn.net/weixin_41205419/article/details/79767489
参考3:《Java面试突击3.0》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值