RandomAccess标记接口

1. 介绍 标记接口由 List 实现使用,以表明它们支持快速(通常为恒定时间)随机访问。 此接口的主要目的是允许通用算法更改其行为,以便在应用于随机访问列表或顺序访问列表时提供良好的性 能。 用于操纵随机访问列表的佳算法(例如 ArrayList )可以在应用于顺序访问列表时产生二次行为(如 LinkedList )。 鼓励通用列表算法在应用如果将其应用于顺序访问列表之前提供较差性能的算法时,检查 给定列表是否为 instanceof ,并在必要时更改其行为以保证可接受的性能。 人们认识到,随机访问和顺序访问之间的区别通常是模糊的。 例如,一些 List 实现提供渐近的线性访问时 间,如果它们在实践中获得巨大但是恒定的访问时间。 这样的一个 List 实现应该通常实现这个接口。 根据 经验, List 实现应实现此接口,如果对于类的典型实例,此循环:

for (int i=0, n=list.size(); i < n; i++)            
        list.get(i);    

比这个循环运行得更快:

for (Iterator i=list.iterator(); i.hasNext(); )
            i.next();


2. 案例演示1

public class Test01 {
public static void main(String[] args) {
//创建ArrayList集合
List<String> list = new ArrayList<>();
//添加10W条数据 for (int i = 0; i < 100000; i++) {
list.add(i+"a");
} System.out.println(
"----通过索引(随机访问:)----"); long startTime = System.currentTimeMillis();
for (int i = 0; i < list.size(); i++) {
//仅仅为了演示取出数据的时间,因此不对取出的数据进行打印
list.get(i);
}
long endTime = System.currentTimeMillis();
System.out.println("随机访问: "+(endTime-startTime));
System.out.println("----通过迭代器(顺序访问:)----");
startTime = System.currentTimeMillis();
Iterator<String> it = list.iterator();
while (it.hasNext()){
//仅仅为了演示取出数据的时间,因此不对取出的数据进行打印
it.next();
}
endTime = System.currentTimeMillis();
System.out.println("顺序访问: "+(endTime-startTime));
}
}

控制台效果:


  ----通过索引(随机访问:)---- 随机访问: 2 ----通过迭代器(顺序访问:)---- 顺序访问: 3

 

3. 案例演示二

public class Test02 {
    public static void main(String[] args) {
        //创建LinkedList集合
        List<String> list = new LinkedList<>();
        //添加10W条数据
        for (int i = 0; i < 100000; i++) {
            list.add(i+"a");
        }

        System.out.println("----通过索引(随机访问:)----");
 
        long startTime = System.currentTimeMillis();
for (int i = 0; i < list.size(); i++) {
//仅仅为了演示取出数据的时间,因此不对取出的数据进行打印
list.get(i);
}
long endTime = System.currentTimeMillis();
System.out.println("随机访问: "+(endTime-startTime));
System.out.println("----通过迭代器(顺序访问:)----");
startTime = System.currentTimeMillis();
Iterator<String> it = list.iterator();
while (it.hasNext()){
//仅仅为了演示取出数据的时间,因此不对取出的数据进行打印
it.next();
}
endTime = System.currentTimeMillis();
System.out.println("顺序访问: "+(endTime-startTime));
}
}

控制台效果:


  ----通过索引(随机访问:)---- 随机访问: 33759 ----通过迭代器(顺序访问:)---- 顺序访问: 9

 

为什么LinkedList随机访问比顺序访问要慢这么多?这里就不放源码了,直接给出总结。

      由于随机访问的时候源码底层每次都需要进行折半的动作,再经过判断是从头还是从尾部一个个寻找。 而顺序访问只会在获取迭代器的时候进行一次折半的动作,以后每次都是在上一次的基础上获取下一个元素, 因此顺序访问要比随机访问快得多 。

 

实际应用:

 //在遍历集合取出结果集之前面临一个问题,使用普通for遍历好 还是使用迭代器(增强for)?
//特别是数据量特别大的时候一定要考虑! //对返回的集合进行判断,如果返回的集合实现了 RandomAccess 就使用 普通for //否则使用迭代器(增强for)    //下面的list是一个集合    if(list instanceof RandomAccess){ for (int i = 0; i < list.size(); i++) { System.out.println(list.get(i)); } }else { for (Stutb stutb : list) { System.out.println(stutb); } }

 

这些是观看黑马视频时记录下的简单整理笔记,需要更详细的讲解去b站看黑马的视频吧。

RandomAccess标记接口

上一篇:tensorflow实现1 order attention机制


下一篇:Mybatis中 SIMPLE、REUSE、BATCH的区别