文档章节

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

剑啸月
 剑啸月
发布于 2016/10/31 00:19
字数 1177
阅读 4012
收藏 0

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

    日志原链接如下:

    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,使用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;
    }

主函数如下:

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的进一步学习才有可能解开了。

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

    测试环境:

    JDK:1.8.0_101

    CPU:core i7 3630QM

    RAM:16G

    IDE:Intellij IDEA 2016.2.5(64bit)

    OS:windows10

© 著作权归作者所有

剑啸月
粉丝 1
博文 4
码字总数 1794
作品 0
杭州
程序员
私信 提问
加载中

评论(2)

龘_曦
龘_曦
学到了
王孟君
王孟君
抢个沙发
这是我见过最有用的java面试题,面试了无数公司总结的(含答案)

(一小部分题的答案被我略作改动) 1、什么是线程局部变量? 线程局部变量是局限于线程内部的变量,属于线程自身所有,不在多个线程间共享。Java 提供 ThreadLocal 类来支持线程局部变量,是...

Java高级架构
2018/10/15
0
0
JDK之JVM中Java对象的头部占多少byte

先做个铺垫: 在32位机器上word size是32bits,CPU一次性处理32bits,在64位机器上word size是64bits,CPU一次性处理64bits。 Data bus size, instruction size, address size are usually ...

汉斯-冯-拉特
2018/06/30
330
0
java 中 16 进制 HEX 转换成字节码形式的 UTF-8

恩,又碰到个蛋疼的编码转换问题了:要把形如 xE9xBB 的字符串转成中文。。。 在python中我们直接 print "xE9xBBx84" 即可, 在shell中我们直接 echo $'xe9xbbx84' #echo -e 'xe9xbbx84'也行......

大数据之路
2013/02/01
7.5K
1
java实现图片和字符串互相转换的代码

java实现图片和字符串互相转换的代码,也就是说java 转换图片为字符串,将字符串转换成图片显示,具体如下: java 转换图片为字符串,网页代理将字符串转换成图片显示, nod32 用户名和密码该...

李强s
2011/06/05
674
0
Clob,Blob,InputStream,byte 互转

今天用java读取oracle里的Clob字段。本来要转成xml文件的,一顿转换。现在总结一下这个流的互相转换方法。 以下内容来自:http://hi.baidu.com/webidea/item/8965fd99de1034dd1e4271e1 一、b...

王小明123
2012/10/06
8.2K
1

没有更多内容

加载失败,请刷新页面

加载更多

使用TensorFlow的AI程序运行报错AttributeError: module 'tensorflow' has no attribute 'xxx'

使用TensorFlow的AI程序,在运行时报错AttributeError: module 'tensorflow' has no attribute 'xxx',首先检查是否是包路径不对,一般是版本变化所致。...

织梦之魂
今天
3
0
提示浏览器版本低

本文转载于:专业的前端网站➭提示浏览器版本低 网站网页在遇到浏览器低版本(尤其是IE浏览器)时,提示浏览器版本低(如IE8以及以下),建议用户升级浏览器以获得最好体验。以下是代码: 1...

前端老手
今天
6
0
CentOS 7系统增加swap

转载请注明文章出处:CentOS 7系统增加swap swap是位于磁盘上的特殊文件(或分区),属于“虚拟内存”的一部分。通俗点就是内存的备胎,内存充足的情况下,基本上没swap什么事(和设置有关)...

tlanyan
今天
6
0
基于Prometheus和Grafana的监控平台 - 环境搭建

相关概念 微服务中的监控分根据作用领域分为三大类,Logging,Tracing,Metrics。 Logging - 用于记录离散的事件。例如,应用程序的调试信息或错误信息。它是我们诊断问题的依据。比如我们说...

JAVA日知录
今天
6
0
PHP运行时全局构造体

struct _php_core_globals { zend_bool magic_quotes_gpc; // 是否对输入的GET/POST/Cookie数据使用自动字符串转义。 zend_bool magic_quotes_runtime; //是否对运行时从外部资源产生的数据使...

冻结not
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部