在java中,大家肯定都会遇到int类型转String类型的情形,知其然知其所以然。总结加分析一下,int类型转String类型有下面几种方式:  

  1. a+”“
  2. String.valueOf(a)
  3. Integer.toString(a)

  以上三种方法在实际使用过程中都是没有问题的,可是效率上还是有些许区别的,所以写个小程序来对照一下他们的效率:

int a = 123456789;
long start = System.currentTimeMillis();
for (int i=0; i<100000; i++){String m = a+"";
}
long end = System.currentTimeMillis();
Log.e("time", "a+\"\" = " + (end - start));start = System.currentTimeMillis();
for (int i=0; i<100000; i++){String n = String.valueOf(a);
}
end = System.currentTimeMillis();
Log.e("time", "String.valueOf(a) = " +(end-start));start = System.currentTimeMillis();
for (int i=0; i<100000; i++){String n = Integer.toString(a);
}
end = System.currentTimeMillis();
Log.e("time", "Integer.toString(a) = " +(end-start));

最后打印出来的运行时间:

E/time: a+"" = 257
E/time: String.valueOf(a) = 140
E/time: Integer.toString(a) = 159

能够看到在效率上除了a+”“这样的方式之外,其它两种方式的效率差点儿相同。为什么呢?看源代码!

String.valueOf(a) && Integer.toString(a)

  先看看后两种方式的源代码:
String.valueOf(a)->Integer.toString(a)->IntegralToString.intToString(a)->convertInt(null, a)

Integer.toString(a)->IntegralToString.intToString(a)->convertInt(null, a)
能够看到String.valueOf是通过调用Integer.toString实现的,也难怪他们的效率如此接近。

他们最后都会调用到convertInt函数中:

private static String convertInt(AbstractStringBuilder sb, int i) {boolean negative = false;String quickResult = null;if (i < 0) {negative = true;i = -i;if (i < 100) {if (i < 0) {// If -n is still negative, n is Integer.MIN_VALUEquickResult = "-2147483648";} else {quickResult = SMALL_NEGATIVE_VALUES[i];if (quickResult == null) {SMALL_NEGATIVE_VALUES[i] = quickResult =i < 10 ? stringOf('-', ONES[i]) : stringOf('-', TENS[i], ONES[i]);}}}} else {if (i < 100) {quickResult = SMALL_NONNEGATIVE_VALUES[i];if (quickResult == null) {SMALL_NONNEGATIVE_VALUES[i] = quickResult =i < 10 ?

stringOf(ONES[i]) : stringOf(TENS[i], ONES[i]); } } } if (quickResult != null) { if (sb != null) { sb.append0(quickResult); return null; } return quickResult; } int bufLen = 11; // Max number of chars in result char[] buf = (sb != null) ?

BUFFER.get() : new char[bufLen]; int cursor = bufLen; // Calculate digits two-at-a-time till remaining digits fit in 16 bits while (i >= (1 << 16)) { // Compute q = n/100 and r = n % 100 as per "Hacker's Delight" 10-8 int q = (int) ((0x51EB851FL * i) >>> 37); int r = i - 100*q; buf[--cursor] = ONES[r]; buf[--cursor] = TENS[r]; i = q; } // Calculate remaining digits one-at-a-time for performance while (i != 0) { // Compute q = n/10 and r = n % 10 as per "Hacker's Delight" 10-8 int q = (0xCCCD * i) >>> 19; int r = i - 10*q; buf[--cursor] = DIGITS[r]; i = q; } if (negative) { buf[--cursor] = '-'; } if (sb != null) { sb.append0(buf, cursor, bufLen - cursor); return null; } else { return new String(cursor, bufLen - cursor, buf); } }

分析一下,这个函数的工作主要能够分为这几步:

  1. 假设a为负数。将a变成正数,假设a还小于0,直接置为Integer.MIN_VALUE;假设a小于100。则直接使用TENS和ONES数组进行高速计算得出结果。加上’-‘号。直接返回该结果。
  2. 假设a为正数而且小于100。直接使用TENS和ONES数组进行高速计算得出结果返回。
  3. 假设上面两步没有处理完,说明a是大于100的数字,无法直接使用TENS和ONES数组进行高速计算。处理方式就是2位为一步循环处理,每次将这两位使用TENS和ONES数组进行高速计算得出这两位的结果存在数组的对应位置。直到仅仅剩一位。最后剩下的一位使用DIGITS数组得出16进制的结果放在最后。返回结果。

  那么问题来了。当a>=100的时候,那两次while循环为什么会使用0x51EB851FL和0xCCCD这两个数字呢?这个问题不要问我,我也不知道,只是源代码作者凝视写的非常明确了:
// Compute q = n/100 and r = n % 100 as per "Hacker's Delight" 10-8
// Compute q = n/10 and r = n % 10 as per "Hacker's Delight" 10-8
去看《Hacker’s Delight》的10-8章。
  接着另一个问题是TENS和ONES数组,直接看代码。一目了然:

/** TENS[i] contains the tens digit of the number i, 0 <= i <= 99. */
private static final char[] TENS = {'0', '0', '0', '0', '0', '0', '0', '0', '0', '0','1', '1', '1', '1', '1', '1', '1', '1', '1', '1','2', '2', '2', '2', '2', '2', '2', '2', '2', '2','3', '3', '3', '3', '3', '3', '3', '3', '3', '3','4', '4', '4', '4', '4', '4', '4', '4', '4', '4','5', '5', '5', '5', '5', '5', '5', '5', '5', '5','6', '6', '6', '6', '6', '6', '6', '6', '6', '6','7', '7', '7', '7', '7', '7', '7', '7', '7', '7','8', '8', '8', '8', '8', '8', '8', '8', '8', '8','9', '9', '9', '9', '9', '9', '9', '9', '9', '9'
};/** Ones [i] contains the tens digit of the number i, 0 <= i <= 99. */
private static final char[] ONES = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9','0', '1', '2', '3', '4', '5', '6', '7', '8', '9','0', '1', '2', '3', '4', '5', '6', '7', '8', '9','0', '1', '2', '3', '4', '5', '6', '7', '8', '9','0', '1', '2', '3', '4', '5', '6', '7', '8', '9','0', '1', '2', '3', '4', '5', '6', '7', '8', '9','0', '1', '2', '3', '4', '5', '6', '7', '8', '9','0', '1', '2', '3', '4', '5', '6', '7', '8', '9','0', '1', '2', '3', '4', '5', '6', '7', '8', '9','0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
};

每一个数组都是100的长度,都是用来处理0~99这100个数字,个位和十位的处理方式也非常清楚。

  从代码角度来看,这个算法在数字小于100的和大于100的处理方式是不一样的,小于100的高速计算法运行时间会远远短于大于100的方式。验证一下。将a变量改动为10:

E/time: i+"" = 199
E/time: String.valueOf() = 7
E/time: Integer.toString() = 6

确实短了非常多。!!

a+”“

  再来看看a+”“的方式,我承认这样的方式我用的最多了,由于太简单了,java源代码对’+’运算符进行了重载。源代码我找不到啊,只是从网上找一些资料:

The Java language provides special support for the string concatenation operator ( + ), and for conversion of other objects to strings. String concatenation is implemented through the StringBuilder(or StringBuffer) class and its append method. String conversions are implemented through the method toString, defined by Object and inherited by all classes in Java. For additional information on string concatenation and conversion, see Gosling, Joy, and Steele, The Java Language Specification.

地址:http://docs.oracle.com/javase/6/docs/api/java/lang/String.html

能够看到,’+’运算符的主要方式是使用StringBuilder或者StringBuffer来实现的。相似于:

StringBuilder sb = new StringBuilder();
sb.append("");
sb.append(i);
String strI = sb.toString();

再来看看append的源代码:
StringBuffer.append->IntegralToString.appendInt(this, a)->convertInt(sb, i)
能够看到’+’运算符最后也是调用到了同一个函数。仅仅只是第一个參数的sb不为null而已。所以已经非常清楚了,’+’运算符的运行效率不高的原因应该就在之前的new StringBuilder等操作和之后的StringBuilder.toString等操作,反编译class文件也能够得出一样的结论:
http://stackoverflow.com/a/4105406。

  所以a+”“的方式以后就少用一点了,效率不高,也显得不太专业。

扩展

  String 扩展的相关知识:
常量池的内存分配在 JDK6、7、8中有不同的实现:
1. JDK6及之前版本号中,常量池的内存在永久代PermGen进行分配。所以常量池会受到PermGen内存大小的限制。
2. JDK7中,常量池的内存在Java堆上进行分配。意味着常量池不受固定大小的限制了。

3. JDK8中,虚拟机团队移除了永久代PermGen。
关于永久代移除:http://www.infoq.com/cn/articles/Java-PERMGEN-Removed
样例1:

public class StringTest {public static void main(String[] args) {String a = "java";String b = "java";String c = "ja" + "va";}
}

变量 a、b 和 c 都指向常量池的 “java” 字符串,表达式 “ja” + “va” 在编译期间会把结果值”java”直接赋值给c。所以终于的结果 a==c 为 true。

样例2:

public class StringTest {public static void main(String[] args) {String a = "hello ";String b = "world";String c = a + b;String d = "hello world";}
}

我们依据上面知道在 java 中 “+” 运算符实际上是使用 StringBuilder.append 去实现的。所以此时会在 Java 堆上新建一个 String 对象,这个 String 对象终于指向常量池的 “hello world”。所以说此时 c==d 为 false。

只是有种特殊情况。当final修饰的变量发生连接动作时,编译器会进行优化,将表达式结果直接赋值给目标变量:

public class StringTest {public static void main(String[] args) {final String a = "hello ";final String b = "world";String c = a + b;String d = "hello world";}
}

所以此时 c==d 为 true。

引用

http://www.importnew.com/21711.html
http://www.importnew.com/21720.html

java int转String全部方式的效率对照与深入解析相关推荐

  1. Java String到int,Java int到String

    Today we will look at Java String to int conversion and then java int to String conversion. Java pro ...

  2. Java int 转 String 类型,java类型转换

    int类型转String类型有下面几种方式: String var = num + ""; Strng var = String.valueOf(num); String var ...

  3. java int和String类型之间的相互转换

    String --> int 第一种方法:int i = Integer.parseInt(s); 第二种方法:int i = Integer.valueOf(s).intValue(); 两种 ...

  4. java数组复制的方式和效率比较

    java中,数组的复制有以下三种方式: 1. 调用System.arraycopy(Arrays.copyOfRange可以当作第四种,但是底层调用的是System.arraycopy,所以,认为是同 ...

  5. java switch char_Java7中Switch为什么只支持byte、short、char、int、String

    Java 7中,switch的参数可以是String类型了,这对我们来说是一个很方便的改进.到目前为止switch支持这样几种数据类型:byte short int char String .但是,作 ...

  6. Java字符串拼接:int和String类型、String和Sting类型

    一.Int和String拼接成String 1.用+拼接 String str = "abc"; int i = 10; String result = str + i; 2.将i ...

  7. 教拉克丝去面试(一),String转换成int的几种方式

    这是一篇用趣味化的形式给大家来讲java面试, "语不惊人死不休",没错,本篇文章的标题就是这么酷炫,接受不了的同学就别点进来看了,所谓好奇心害死猫:能够接受的同学我只能说你赚到了 ...

  8. Java 中Int转String的三种方法

    JAVA 中int类型转String类型的三种通常方法: 1.String.valueOf(int i) 2.Integer.toString(int i) 3.i + ""; / ...

  9. java indexof int,int indexOf(String str, int fromIndex)

    int indexOf(String str, int fromIndex) 描述 (Description) java.lang.String.indexOf(String str, int fro ...

最新文章

  1. 多模态人物识别技术及其在爱奇艺视频场景中的应用 | 公开课笔记
  2. 【caffe解读】 caffe从数学公式到代码实现4-认识caffe自带的7大loss
  3. 浅谈:Android应用清理内存
  4. 定量遥感:计算地方时和太阳高度角(C++代码)
  5. java 泛型和类型擦除_关于Java泛型和擦除
  6. php mysql读取数据查询_PHP MySQL 读取数据
  7. android 图片叠加xml,Android实现图片叠加效果的两种方法
  8. 拳王虚拟项目公社:虚拟商品全自动化赚钱技术,虚拟产品自动赚钱能信吗?虚拟资源教程
  9. 计算机一级综合第九套试题及答案,2012年计算机一级B第九套选择题精选及参考答案...
  10. 【C#】图片处理(底片,黑白,锐化,柔化,浮雕,雾化)
  11. html文本框上下左右移动,基于jQuery实现文本框缩放以及上下移动功能
  12. AirPlay/ios浅谈
  13. 您的服务器组件没有得到合法授权,服务器将会受限模式运行
  14. pathon学习日记
  15. 使用Excel连接WINCC生成报表的实现方法
  16. iOS小技能:监听H5页面goBack返回事件 网页监听APP返回键 (NavigationBackItemInjection)
  17. MTK 安卓11 传感器兼容 陀螺仪42607-p
  18. HTML学习07(实践1):HTML常用标签之标题、段落、换行、空格、列表
  19. 【HTML】之marquee标签的使用和说明
  20. 仓库摆放示意图_仓库合理堆放标准,货物入库摆放规范

热门文章

  1. 2!=5 or 0在python中是否正确-Python 中的 or and 运算,看这一篇就够
  2. python经典小游戏-又一个python小游戏,叫什么不知道了。。。
  3. 农业银行联行号怎么查询_农行信用卡解析丨菜卡怎么提额8W?学会一招就够了!...
  4. Revising the Select Query I(单表查询)
  5. php Session存储到Redis的方法
  6. 用脚本批量执行redis命令
  7. win8.1升级到win10后 vmware不能连网的问题
  8. Java中的抽象类和方法
  9. SDOI2015寻宝游戏 dfs序+set
  10. 理解ffmpeg中的pts,dts,time_base