一. 何为标记接口
没有任何方法和属性的接口称为标记接口,它仅仅表明实现它的类属于一个特定的类型,可以当做标记对待, 例如java.io.Serializable接口,实现了这个接口的类,就表明这个类可以序列化和反序列化。
二. RandomAccess用法
RandomAccess 是一个标记接口,主要用于List集合里面,目的是使算法能够在随机和顺序访问的list中表现的更加高效
1. 源码中ArrayList实现了RandomAccess接口
2. 源码中LinkedList没有实现RandomAccess接口
3. RandomAccess对ArrayList和LinkedList有什么作用呢
通过查看Collections工具类源码中的binarySearch方法:
如果参数中的list实现了RandomAccess接口,则调用Collections.indexedBinarySearch(list, key)遍历。
如果参数中的list没有实现RandoomAccess接口,则调用Collections.iteratorBinarySearch(list, key);遍历。
比较两个方法:一个采用for循环,一个采用迭代器,这两种有什么不一样呢。
arrayList通过for循环遍历:
arrayList通过迭代器循环遍历:
LinkedList通过for循环遍历:
LinkedList通过迭代器循环遍历:
main方法:
执行结果:
结论:
从上面数据可以看出,ArrayList用for循环遍历比迭代器遍历快,LinkedList用迭代器遍历比for循环遍历快。
三. RandomAccess的使用场景
通过RandomAccess标记,我们能判断出List接口是ArrayList还是LinkedList,从而能够更好选择更优的遍历方式,提高性能
四. 造成两种遍历方式效率不一样的原因是什么呢
1. 分析ArrayList和LinkedList的区别:
1)因为 Array 是基于索引 (index) 的数据结构,它使用索引在数组中搜索和读取数据是很快的。 Array 获取数据的时间复杂度是 O(1), 但是要更新数据却是开销很大的,因为需要重排数组中的所有数据。
2). 相对于 ArrayList , LinkedList 插入是更快的。因为 LinkedList 不像 ArrayList 一样,不需要改变数组的大小,也不需要在数组装满的时候要将所有的数据重新装入一个新的数组,这是 ArrayList 最坏的一种情况,时间复杂度是 O(n) ,而 LinkedList 中插入或删除的时间复杂度仅为 O(1) 。 ArrayList 在插入数据时还需要更新索引(除了插入数组的尾部).
3).LinkedList 需要更多的内存,因为 ArrayList 的每个索引的位置是实际的数据,而 LinkedList 中的每个节点中存储的是实际的数据和前后节点的位置 ( 一个 LinkedList 实例存储了两个值: Node first 和 Node last 分别表示链表的其实节点和尾节点,每个 Node 实例存储了三个值: E item,Node next,Node pre) 。
换句话说,ArrayList的实现用的是数组,LinkedList是基于链表,ArrayList适合查找,LinkedList适合增删。
2. 迭代器和for循环的区别:
for循环适合访问顺序结构,可以根据下标快速获取指定元素.而Iterator 适合访问链式结构,因为迭代器是通过next()和Pre()来定位的.可以访问没有顺序的集合.,foreach(增强型for循环)内部实现就是一个迭代器。