`
jianchen
  • 浏览: 343070 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

RandomAccess接口的使用

阅读更多
引子:
RandomAccess在类Collections的shuffle()方法中的使用:(jdk源码如下)
/**
     * Randomly permute the specified list using the specified source of
     * randomness.  All permutations occur with equal likelihood
     * assuming that the source of randomness is fair.<p>
     *
     * This implementation traverses the list backwards, from the last element
     * up to the second, repeatedly swapping a randomly selected element into
     * the "current position".  Elements are randomly selected from the
     * portion of the list that runs from the first element to the current
     * position, inclusive.<p>
     *
     * This method runs in linear time.  If the specified list does not
     * implement the {@link RandomAccess} interface and is large, this
     * implementation dumps the specified list into an array before shuffling
     * it, and dumps the shuffled array back into the list.  This avoids the
     * quadratic behavior that would result from shuffling a "sequential
     * access" list in place.
     *
     * @param  list the list to be shuffled.
     * @param  rnd the source of randomness to use to shuffle the list.
     * @throws UnsupportedOperationException if the specified list or its
     *         list-iterator does not support the <tt>set</tt> operation.
     */


public static void shuffle(List<?> list, Random rnd) {
        int size = list.size();
        if (size < SHUFFLE_THRESHOLD || list instanceof RandomAccess) {//注意这一句中的instanceof
            for (int i=size; i>1; i--)
                swap(list, i-1, rnd.nextInt(i));
        } else {
            Object arr[] = list.toArray();

            // Shuffle array
            for (int i=size; i>1; i--)
                swap(arr, i-1, rnd.nextInt(i));

            // Dump array back into list
            ListIterator it = list.listIterator();
            for (int i=0; i<arr.length; i++) {
                it.next();
                it.set(arr[i]);
            }
        }
    }

 由以上的jdk源码可见,在对实现list接口的对象进行洗牌,打乱时,区分了该类是否是RandomAccess的实例,这样做有什么意义呢?请继续向下看:


介绍:

在jdk文档中对RandomAccess接口的定义如下:

public interface RandomAccess

List 实现所使用的标记接口,用来表明其支持快速(通常是固定时间)随机访问。此接口的主要目的是允许一般的算法更改其行为,从而在将其应用到随机或连续访问列表时能提供良好的性能。


将操作随机访问列表的最佳算法(如 ArrayList )应用到连续访问列表(如 LinkedList )时,可产生二次项的行为。如果将某个算法应用到连续访问列表,那么在应用可能提供较差性能的算法前,鼓励使用一般的列表算法检查给定列表是否为此接口的一个 instanceof ,如果需要保证可接受的性能,还可以更改其行为。

现在已经认识到,随机和连续访问之间的区别通常是模糊的。例如,如果列表很大时,某些 List 实现提供渐进的线性访问时间,但实际上是固定的访问时间。这样的 List 实现通常应该实现此接口。


强调:

JDK中推荐的是对List集合尽量要实现RandomAccess接口

如果集合类是RandomAccess的实现,则尽量用for(int i = 0; i < size; i++) 来遍历而不要用Iterator迭代器来遍历,在效率上要差一些。反过来,如果List是Sequence List,则最好用迭代器来进行迭代。


JDK中说的很清楚,在对List特别是Huge size的List的遍历算法中,要尽量来判断是属于RandomAccess(如ArrayList)还是Sequence List (如LinkedList),因为适合RandomAccess List的遍历算法,用在Sequence List上就差别很大,常用的作法就是:
    要作一个判断:
    if (list instance of RandomAccess) {
        for(int m = 0; m < list.size(); m++){}
    }else{
        Iterator iter = list.iterator();
        while(iter.hasNext()){}
    }


验证:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package testrandomaccess;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.RandomAccess;

/**
 *
 * @author bolong
 */
public class TestRandomAccess {
// 初始化列表

    public static void initList(List list, int n) {
        for (int i = 0; i < n; i++) {
            list.add(i);
        }
    }
//使用循环进行对列表的迭代

    public static void traverseWithLoop(List list) {
        long starttime = 0;
        long endtime = 0;
        starttime = System.currentTimeMillis();
        for (int count = 0; count <= 1000; count++) {
            for (int i = 0; i < list.size(); i++) {
                list.get(i);
            }
        }
        endtime = System.currentTimeMillis();
        System.out.println("使用loop迭代一共花了" + (endtime - starttime) + "ms时间");

    }
//使用迭代器对列表进行迭代

    public static void traverseWithIterator(List list) {
        long starttime = 0;
        long endtime = 0;
        starttime = System.currentTimeMillis();
        for (int count = 0; count <= 1000; count++) {
            for (Iterator itr = list.iterator(); itr.hasNext();) {
                itr.next();
            }
        }
        endtime = System.currentTimeMillis();
        System.out.println("使用Iterator迭代一共花了" + (endtime - starttime) + "ms时间");
    }

    public static void traverse(List list) {

        long starttime = 0;
        long endtime = 0;
        if (list instanceof RandomAccess) {
            System.out.println("该list实现了RandomAccess接口");
            starttime = System.currentTimeMillis();
            for (int count = 0; count <= 1000; count++) {
                for (int i = 0; i < list.size(); i++) {
                    list.get(i);
                }
            }
            endtime = System.currentTimeMillis();
            System.out.println("迭代一共花了" + (endtime - starttime) + "ms时间");
        } else {
            System.out.println("该list未实现RandomAccess接口");
            starttime = System.currentTimeMillis();
            for (int count = 0; count <= 1000; count++) {
                for (Iterator itr = list.iterator(); itr.hasNext();) {
                    itr.next();
                }
            }
            endtime = System.currentTimeMillis();
            System.out.println("迭代一共花了" + (endtime - starttime) + "ms时间");
        }
    }

    public static void main(String[] args) {
        ArrayList arraylist = new ArrayList();
        LinkedList linkedlist = new LinkedList();
        initList(arraylist, 1000);
        initList(linkedlist, 1000);
        traverse(arraylist);
        traverse(linkedlist);
        traverseWithIterator(arraylist);
        traverseWithLoop(arraylist);
        traverseWithIterator(linkedlist);
        traverseWithLoop(linkedlist);
    }
}

 运行程序输出的结果为:


该list实现了RandomAccess接口
迭代一共花了47ms时间
该list未实现RandomAccess接口
迭代一共花了15ms时间
使用Iterator迭代一共花了79ms时间
使用loop迭代一共花了46ms时间
使用Iterator迭代一共花了47ms时间
使用loop迭代一共花了797ms时间


结论:

根据程序输出的结果的确证明了,arraylist等实现了RandomAccessj接口的类在进行迭代时使用loop效率更高,而linkedList那些未实现该接口的类在进行迭代时使用Iterator进行迭代效率更高.

分享到:
评论

相关推荐

    了解Java:RandomAccess

    描述中的链接指向了一篇2012年的博客文章,虽然具体内容没有提供,但通常这样的文章会深入讲解如何在Java中使用RandomAccess接口或者类,如java.io.RandomAccessFile,它允许对文件进行随机读写操作。...

    java 中RandomAccess接口源码分析

    如果List实现满足以下条件,即循环遍历列表元素的速度快于使用迭代器遍历列表元素的速度,那么该List实现就应该实现RandomAccess接口: ```java for (int i=0, n=list.size(); i ; i++) list.get(i); ``` 与 ```...

    Java接口RandomAccess全面了解

    在`ArrayList`上,使用`for`循环遍历(实现了`RandomAccess`接口的遍历方式)仅花费10毫秒,而使用迭代器遍历则需要39毫秒。相反,对于`LinkedList`,由于它不支持`RandomAccess`,迭代器遍历(27毫秒)比基于索引的...

    前端开源库-random-access-memory

    在前端开发中,`random-access-memory` 库是一个创新的开源项目,它模仿了传统的随机存取文件接口,但其数据存储位置并非硬盘上的文件,而是浏览器的内存。这种设计使得开发者可以利用内存的优势进行高性能的数据...

    今天会是有Offer的一天么:面试时不要再问我ArrayList、LinkedList和CopyOnWriteArrayList的区别了

    今天不看源码(想看源码的同学可以自己在...实现RandomAccess接口表示它可以支持随机访问(强调一点,并不是因为实现了RandomAccess接口,ArrayList才支持随机访问。RandomAccess只是一个标记接口,接口RandomAccess中

    前端开源库-random-access-file

    `random-access-file` 库提供了一种在浏览器中实现这一功能的方法,它使用了Blob对象和FileReader/FileWriter API。Blob对象是用于存储不可变原始数据的类文件对象,而FileReader/FileWriter则提供了对这些数据的...

    从原码解析ArrayList

    在Collections工具类的某些算法中,例如二分查找,会根据对象是否实现RandomAccess接口来选择使用索引还是迭代器的方式进行查找,前者效率更高。这是因为ArrayList底层基于数组,可以通过索引直接访问,而LinkedList...

    外文翻译-SDRAM接口电路设计

    SDRAM(Synchronous Dynamic Random Access Memory)接口电路设计是现代计算机系统中至关重要的部分,它连接CPU与内存,确保数据快速、高效地传输。近年来,随着计算机性能的提升,SDRAM接口的数据速率大幅增加,以...

    93-SRAM接口设计.7z

    在电子设计领域,静态随机存取存储器(Static Random Access Memory,简称SRAM)是一种常见的高速缓存存储器,常用于FPGA(Field-Programmable Gate Array)设计中。本资源"93-SRAM接口设计.7z"提供了一个关于SRAM...

    Java Collections Interview Questions.pdf

    RandomAccess 接口是 Java Collections 框架中的一个标记接口,用于标记实现了随机访问的集合类。ArrayList 等类实现了 RandomAccess 接口,提供了随机访问的功能。 Comparable 和 Comparator 的区别 Comparable ...

    电脑主板接口图解.doc

    4. **内存插槽**:DDR4、DDR3等类型的RAM(Random Access Memory)通过这些插槽安装到主板上,以提供系统的临时数据存储,提高处理速度。 5. **PCI-E扩展槽**:PCI Express(PCI-E)扩展槽用于添加显卡、网卡、声卡...

    高性能DDR2 SDRAM接口设计

    DDR2 SDRAM(Double Data Rate 2 Synchronous Dynamic Random Access Memory)是一种高带宽的内存类型,能够在每个时钟周期的上升沿和下降沿传输数据,从而显著提升数据传输速率。为了充分利用DDR2 SDRAM的能力,...

    ARM外围器件接口资料

    5. **存储器件接口**:这包括闪存(Flash Memory)和RAM(Random Access Memory)接口。闪存通常用作系统固件的存储,如Bootloader、操作系统和应用程序。RAM则用于运行时的数据存储。常见的闪存接口有SPI、I²C和...

    GSM网络空中接口浅析

    - CCCH(Common Control Channel)双向信道,包含RACH(Random Access Channel,用于移动台接入系统)、PCH(Paging Channel,用于寻呼移动台)和AGCH(Access Granted Channel,分配SDCCH等资源)。 - DCCH...

    基于FPGA的DDR3用户接口设计.pdf

    DDR3(Double Data Rate 3 SDRAM,双倍数据速率3同步动态随机存取存储器)是一种高效率的RAM(Random Access Memory)类型,用于计算机和个人电子设备。它支持更高的数据速率和更低的电压,比前代技术DDR2有更高的...

    基于FPGA的机载合成孔径雷达数字信号处理机接口板卡的设计与实现.docx

    硬件FIFO(First-In-First-Out,先进先出)和软件双口RAM(Random Access Memory,随机存取存储器)用于缓存和存储数据。 4. 系统硬件结构设计: 机载合成孔径雷达数字信号处理机接口板卡的硬件结构设计中,FPGA...

    DDR4接口标准

    DDR4(Double Data Rate 4)作为一种高性能的动态随机存取存储器(Dynamic Random Access Memory,简称DRAM),在提高数据传输速率的同时降低了功耗,成为了当前主流的内存技术标准。 #### 二、DDR4标准概述 DDR4...

    java关键字ArrayList详解

    ArrayList继承自AbstractList,实现了List接口,RandomAccess接口,Cloneable接口和Serializable接口。实现List接口意味着ArrayList必须提供一系列用于添加、删除、修改和查找元素的方法。RandomAccess接口是一个...

    SDRAM接口模块的VeriogHDL设计

    SDRAM(Synchronous Dynamic Random Access Memory)是一种同步动态随机存取内存,它与系统时钟同步工作,提供较高的数据传输速率。在FPGA中,设计SDRAM接口是实现高效数据处理的关键步骤。 本设计主题是“SDRAM...

    ArrayList、Vector、LinkedList 的区别.docx

    此外,ArrayList 和 Vector 还实现了 RandomAccess 接口,该接口提供了快速随机访问存储的元素的功能,而 LinkedList 实现了 Deque 接口,该接口支持双向队列。同时,三个类都实现了 Cloneable 接口,支持调用 ...

Global site tag (gtag.js) - Google Analytics