在我多年的开发经验中,经常发现的一个情况就是,很多项目的对象字段或者是数据库字段本来是数字类型的,却被定义成字符串类型,这无关痛痒吗?
对于小项目来说,可能没什么影响,反正只要业务逻辑正确即可,性能没什么问题,因为数据也不多,用户也不多。
然而,对于大数据处理来说,这个可不是小事,从字符串替换为数字类型,可以极大地节省内存、磁盘存储以及网络带宽,减少IO的代价,而且很多数据结构和算法使用数字类型比字符串要更快。
我们来看一个例子,假设你有很多的日志需要处理,而每条日志都有一个唯一的标识,标识类似这样的格式:
F5051582611729507844 3832154813577306424 F1624235934976711017 3810376634214027595 F6884923813121317381 7278044081826528150
看到这些标识,你怎么想?我的第一反应应该是数字,可是怎么有个F呢?我想可以把它当做16进制。后来发现可以把F当做负号,这就是一个64位的长整型。
那么如果你把这些标识当成字符串,会有什么不同呢?
当然有,如果你每秒要处理这样的日志百万或者千万条,每条处理结果可能会包含百万或者千万个这样的标识元素构成的集合,这个不同就会体现的非常明显。
下面,我们来分析一下标识3832154813577306424的存储占用情况:
1、内存占用
当做字符串:我们知道,JAVA中字符串是由字符构成的,一个字符是由2个字节构成的(这是JAVA的悲剧了),上述标识有19个字符,所以,占用的内存大小为:19*2+4=42(字节),+4是因为字符串使用一个整型保存字符串的哈希值。
当做数字:如当做长整型,则占用的内存大小为8字节。
这里有5倍以上的差距了吧。
2、序列化字节大小
当我们需要通过网络传输这些标识或者需要把这些标识存储到磁盘中的时候,我们就需要把这些标识转换为字节数组,如何转换为字节数组呢?我们可以使用多种编码方式。
当做字符串:我们知道,JAVA中字符串转换为字节数组可以使用多种编码方式,我们看看常见的编码方式对如上字符串编码之后的字节数:
String abc = "3832154813577306424"; System.out.println("3832154813577306424 length:"+abc.length()); System.out.println(Charset.defaultCharset().name()+":"+abc.getBytes().length); System.out.println("unicode:"+abc.getBytes("unicode").length); System.out.println("gbk:"+abc.getBytes("gbk").length); System.out.println("gb2312:"+abc.getBytes("gb2312").length); System.out.println("ISO-8859-1:"+abc.getBytes("ISO-8859-1").length);
输出如下:
3832154813577306424 length:19 UTF-8:19 unicode:40 gbk:19 gb2312:19 ISO-8859-1:19
当做数字:如当做长整型,则占用的内存大小为8字节。
这里有2倍以上的差距了吧。
那么我们如何在长整型和字节数组之间转换呢?
String abc = "3832154813577306424"; System.out.println("3832154813577306424 length:"+abc.length()); System.out.println("long:"+ByteUtils.longToBytes(Long.parseLong(abc)).length); byte[] bytes = ByteUtils.longToBytes(Long.parseLong(abc)); System.out.println("string:"+ByteUtils.bytesToLong(bytes));
输出如下:
3832154813577306424 length:19 long:8 string:3832154813577306424
public static byte[] longToBytes(long x) { ByteBuffer longBuffer = ByteBuffer.allocate(Long.BYTES); longBuffer.putLong(0, x); return longBuffer.array(); } public static long bytesToLong(byte[] bytes) { return bytesToLong(bytes, 0, bytes.length); } public static long bytesToLong(byte[] bytes, int offset, int length) { ByteBuffer longBuffer = ByteBuffer.allocate(Long.BYTES); longBuffer.put(bytes, offset, length); longBuffer.flip();//need flip return longBuffer.getLong(); }
相关推荐
详解C++中十六进制字符串转数字(数值) 主要有两个方法,其实都是对现有函数的使用: 方法1: sscanf() 函数名: sscanf 功 能: 从字符串格式化输入 用 法: int sscanf(char *string, char *format[,...
主要介绍了java基础-给出一个随机字符串,判断有多少字母?多少数字?文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
oracle通过sql实现字符串转数字oracle函数,可用于字符串的最终排序
oracle里面没有sql server里面的类似函数is_number来判断能否转换为数字,怎么办?本文给出答案。
判断字符串是否为数字
java将字符串中数字转换为中文大写,在输出字符串java将字符串中数字转换为中文大写,在输出字符串java将字符串中数字转换为中文大写,在输出字符串java将字符串中数字转换为中文大写,在输出字符串java将字符串中数字...
字符串转数字
将数字从字符串中提取,源码 已运行无错,可直接使用
获取一个字符串中的数字组 /*输入一个字符串,内有数字和非数字字符,如a123x456_17960? 302tab5876,将其中连续的数字作为一个整数,请统计出一共有多少个整数,输出这些整数,并求出最长的整数的位数。*/
字符串和数字转换 C++ vs2008实现
第一行输入有多少个字符串,后面输入对应的字符串,输出每个字符串输出一个数字,对应该字符串中数字的个数
从键盘输入一个字母+数字的字符串,统计数字所出现位置
本文阐述:shell中整数比较方法及字符串的比较方法,如等于,不等于,大于,大于等于,小于,等等
判断一行字符串中的数字出现的个数。 Input 输入只有一行。输入一个字符串,该字符串中可以包含&^$^#@*任何符号以及空格。输入以回车结束。 Output 有多行。输出该字符串中每个出现过的数字,然后在冒号“:”...
用汇编语言实现,输入一个字符串,然后检索数字,并去掉 用汇编语言实现,输入一个字符串,然后检索数字,并去掉 用汇编语言实现,输入一个字符串,然后检索数字,并去掉 用汇编语言实现,输入一个字符串,然后检索...
将一个停含有数字的字符串中的数字全移到非数字字符之后,并保持数字字符(还有非数字字符)相对顺序不变.
C#判断字符串是否为数字字符串
随机生成字符串,数字,字符串和数字混合,vs2008,c#
把一个数字字符串转换为整形,数字可以是大于2147483648的数字,可以是负数也可以是正数
两种方法获取字符串中的数字代码