关于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其实还有很多话聊深浅拷贝啊,设计模式啊,序列化方式啊,今天就记这么多了,如果有收获,可以点赞鼓励哦😯