关于ArrayList和LinkedList区别,你可能忽略的RandomAccess接口

关于ArrayList和LinkedList RandomAccess接口

在这里插入图片描述

1.ArrayList和Linkedlist

面试常问ArrayList和LinkedList有什么区别,

  • ArrayList底层是基于动态数组实现,LinkedList是基于双向链表实现
  • 对于数组,我们知道随机访问速度快,因为可以通过索引也就是下标,或者说是指针。当然数组的缺点也很明显,在插入和删除时,数组的元素可能要移位。
    链表插入和删除都很快,只是指针的指向改变,但是查找就要一个个遍历了,这也是它的缺点。

以上其实最主要还是基于存储上,数组是连续存储的,这也就是为什么能通过下标来获取元素值(通过下标可以及时到第几个的元素)
链表是碎片化的存储方式,好处当然也有,那就是不会浪费内存,比较灵活。

在这里插入图片描述
在这里插入图片描述

2.RandomAccess

说了这么多,还有一点就是容易忽略,其实在工作中可能会提升运行效率,就是今天的主角RandomAccess。

在ArrayList中,它实现了List,RandomAcces,Cloneable,Serializable四个接口,在这四个接口中我们点开看会发现RandomAcces,Cloneable,Serializable接口什么都没有
这些什么都没有的接口其实就是java中标记接口。那么什么是标记接口呢?

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

标记接口就是告诉我们程序员这个接口能干什么。RandomAccess就是支持随机访问,也就是说可以通过下标就行访问,在集合遍历时,通常情况下有二个大致的方向,
要么是for循环,要么是迭代遍历。那么RandomAccess的作用就来了,就是告诉我们这个集合for循环要比迭代快一点。

通过下面代码实操我们也证明了这点:

public static void arrayListFor(){
        ArrayList arrayList = new ArrayList();
        for (int i = 0;i < 1000000; i++){
            arrayList.add(i);
        }
        long start = System.currentTimeMillis();
        for (int i = 0; i < arrayList.size(); i++){
            Object o = arrayList.get(i);
        }
        long end = System.currentTimeMillis();
        long time = end - start;
        System.out.println("arrrayListFor循环时间:" + time);
    }
    public static void arrayListIterator(){
        ArrayList arrayList = new ArrayList();
        for (int i = 0;i < 1000000; i++){
            arrayList.add(i);
        }
        Iterator iterator = arrayList.iterator();
        long start = System.currentTimeMillis();
        while (iterator.hasNext()){
            Object o = iterator.next();
        }
        long end = System.currentTimeMillis();
        long time = end - start;
        System.out.println("arrrayListIterator循环时间:" + time);
    }

在这里插入图片描述

我们知道数组的访问比链表快一点,所以一般基于数组实现的类都有RandomAccess接口,类似的有Vector,CopyOnWriteArrayList。

而LinkedList就适合迭代遍历,我就代码不贴上去了。工作时,怎样判断用哪种遍历的方式呢,可以通过instanceof来判断是否实现RaddomAccess接口。

在Collections中有个查找list中元素位置的方法binarySearch。它就通过instanceof判断遍历的方式

public static <T>
    int binarySearch(List<? extends Comparable<? super T>> list, T key) {
        if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)
            return Collections.indexedBinarySearch(list, key);
        else
            return Collections.iteratorBinarySearch(list, key);
    }

3.others

再简单聊一聊另外二个标记接口Cloneable和Serializable,我们都知道所以的类默认都继承Object类,在Object类中有个clone方法

protected native Object clone() throws CloneNotSupportedException;

如果某个类实现了Cloneable接口,就是告诉我们这个类可以clone;

如果没有实现Cloneable接口,就会抛出异常

java.lang.CloneNotSupportedException: Test3
	at java.lang.Object.clone(Native Method)
	at Test3.main(Test3.java:12)

Serializable接口就是序列化

由于对象要保存到磁盘或在网络上传输,比如远程调用,那么必须要保证对象的可序列化。

  • 序列化:将对象写入到IO流中
  • 反序列化:从IO流中恢复对象

建议最好每个JavaBean都要实现Serializable接口。

🤔嗯嗯

这里只是简单的介绍了clone和Serializable,clone其实还有很多话聊深浅拷贝啊,设计模式啊,序列化方式啊,今天就记这么多了,如果有收获,可以点赞鼓励哦😯

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值