Java中List转换为byte[]方法比较

    在工做中,遇到了对byte数组的一些处理。目的是根据已有的信息编辑成一组数组并发送给设备。在整个处理过程当中,发现直接处理byte数组十分麻烦,须要屡次用到数组copy之类的操做,数组的下标操做也比较恶心。后来通过多方查找,发现先利用List<Byte>构建数组内容,无需在意下标位置,也不用数组copy,只须要无脑Add就能够很方便的构建整个数组,再把List转换为byte[]就能够了。在探索了整个过程以后,发现一篇博文推荐了三种List<Byte>转换为byte[]的方法,并简要说了一句三者的速度差别。我对这个过程比较好奇,所以本身作了一些小小的比较,算是对工做遇到的问题的一个总结。但愿对你们有所帮助。java

    日志原连接以下:windows

    http://blog.csdn.net/jenlyser/article/details/17024875数组

    文中提到了三种方法,分别是1——使用for循环。2——使用Apache Commons Lang库的ArrayUtils.toPrimitive()方法。3——google guava中的Bytes.toArray()方法。并说起这三种方法中第一种最慢,第二种稍快,第三种最快。我这里第二种方法始终报错,彷佛是ArrayUtils.toPrimitive()方法并不支持List<>类型的参数。所以只是简单比较了第1、三种方法的速度。代码以下:并发

    

/**
     * 方法1,使用for循环
     * @param list
     * 将被转换为byte[]的List<Byte>
     * @return
     * 转换成的byte数组
     */
    private static byte[] listTobyte1(List<Byte> list) {
        if (list == null || list.size() < 0)
            return null;
        byte[] bytes = new byte[list.size()];
        int i = 0;
        Iterator<Byte> iterator = list.iterator();
        while (iterator.hasNext()) {
            bytes[i] = iterator.next();
            i++;
        }
        return bytes;
    }

    /**
     * 方法3,使用guaba的Bytes.toArray()方法
     * @param list
     * 将被转换为byte[]的List<Byte>
     * @return
     * 转换成的byte数组
     */
    private static byte[] listTobyte2(List<Byte> list) {
        byte[] bytes= Bytes.toArray(list);
        return bytes;
    }

主函数以下:dom

public static void main(String[] args) {

        List<Byte> bytesList= new ArrayList<Byte>();
        Random rand = new Random(128);
        for (int i = 0; i < 10000000 ; i ++){//测试数量
            bytesList.add((byte)rand.nextInt());
        }

        long startTime1=System.currentTimeMillis();   //获取开始时间
        listTobyte1(bytesList);
        long endTime1=System.currentTimeMillis(); //获取结束时间
        System.out.println("方法1运行时间: "+(endTime1-startTime1)+"ms");

        long startTime2=System.currentTimeMillis();   //获取开始时间
        listTobyte2(bytesList);
        long endTime2=System.currentTimeMillis(); //获取结束时间
        System.out.println("方法2运行时间: "+(endTime2-startTime2)+"ms");

    }

    接下来将分别测试长度为1000 / 10000 / 50000 / 100000 / 1000000 / 10000000 / 50000000的List转换耗时:函数

  1000  10000 50000 100000 1000000 10000000 50000000
for循环 1ms 2ms 8ms 13ms 17ms 111ms 132ms
guava 5ms 6ms 7ms 10ms 16ms 35ms 183ms

    通过测试,能够很明显的发现,在List容量小于10W个的时候,使用for循环明显快于guava库中的Bytes.toArray()方法。数量越小差距越大。当List容量在10W~1000W个的时候,for循环方法被反超,速度大幅度落后于guava。而数据量超过5000W时,guava方法又大幅度落后了。总体形式十分交错纠结。我又加测了容量为1亿时两者的速度,for循环耗时277ms,guava耗时320ms。结果与以前趋势相符。学习

    为了进一步比较两者速度反超时候的状况,我又加测了1000W~5000W容量的数据。以1000W为起点,500W为一个节点进行递增。结果以下:测试

  1000W 1500W 2000W 2500W 3000W 3500W 4000W 4500W 5000W
for循环 116ms 168ms 205ms 260ms 300ms 111ms 117ms 154ms 137ms
guava 37ms 49ms 64ms 10823ms 120ms 158ms 163ms 162ms 179ms

    结果然的好诡异,尤为是2500W这一组,guava方法时间异常的多。为了防止出错我反复检查了list的大小和执行的结果,然而每次guava耗时都在10~11秒左右。而过了这个区间之后在3000W容量下两者耗时恢复正常,3500W以后for循环方法耗时不增反降,guava方法的耗时也趋于平缓。呈现出一个十分奇怪的趋势。这个趋势我目前还没法给出结论。只是在List长度为5W之内,for循环方法耗时更小,5W~2000W,能够选择guava提供的Bytes.toArray()方法以节约时间。而到了2000W以上,仍是用for循环更为实惠。在考虑平常的应用场景,普通的for循环方法应该是足够覆盖大多数使用场景了。而guava方法诡异的时间趋势的秘密,只有之后经过对源码和JVM的进一步学习才有可能解开了。google

    感谢上文提到的列出三个方法的做者。spa

    测试环境:

    JDK:1.8.0_101

    CPU:core i7 3630QM

    RAM:16G

    IDE:Intellij IDEA 2016.2.5(64bit)

    OS:windows10

相关文章
相关标签/搜索