我想从字符重新presenting十六进制值转换(大写或小写),以字节,像
0 - 大于0,1 - > 1,'A' - > 10,A - > 10,'F' - > 15等...
我会调用这个方法非常频繁,所以性能是非常重要的。有没有更快的方式比使用pre-初始化的HashMap<性格,字节>
得到的值
答案
看起来这是使用一个开关外壳和乔恩斯基特的直接计算解决方案之间的tossup - 开关情况下的解决方案似乎边出非常轻微,但 Greg的阵法胜出。这里有绩效考核的结果(以毫秒)的各种方法200,000,000运行:
Character.getNumericValue:
8360
Character.digit将:
8453
HashMap的<性格,字节计算值:
15109
格雷格的阵列方法:
6656
JonSkeet直接法:
7344
开关:
7281
谢谢你们!
基准测试方法,code
下面雅去,JonSkeet,你这个老对手。 ; - )
公共类暂存器{
私有静态最终诠释NUMBER_OF_RUNS = 2亿;
静态字节水库;
静态的HashMap<性格,字节>图=新的HashMap<性格,字节>(){{
把(Character.valueOf('0'),Byte.valueOf((字节)0));
把(Character.valueOf(1),Byte.valueOf((字节),1));
放(Character.valueOf('2'),Byte.valueOf((字节)2));
放(Character.valueOf('3'),Byte.valueOf((字节3)3));
放(Character.valueOf('4'),Byte.valueOf((字节)4));
放(Character.valueOf('5'),Byte.valueOf((字节)5));
把(Character.valueOf(6),Byte.valueOf((字节)6));
把(Character.valueOf('7'),Byte.valueOf((字节)7));
把(Character.valueOf(8),Byte.valueOf((字节)8));
把(Character.valueOf('9'),Byte.valueOf((字节)9));
放(Character.valueOf('a')的,Byte.valueOf((字节)10));
把(Character.valueOf(B),Byte.valueOf((字节)11));
把(Character.valueOf('C'),Byte.valueOf((字节)12));
把(Character.valueOf(D),Byte.valueOf((字节)13));
把(Character.valueOf(E),Byte.valueOf((字节)14));
把(Character.valueOf('F'),Byte.valueOf((字节)15));
把(Character.valueOf('A'),Byte.valueOf((字节)10));
放(Character.valueOf('B'),Byte.valueOf((字节)11));
把(Character.valueOf('C'),Byte.valueOf((字节)12));
把(Character.valueOf(D),Byte.valueOf((字节)13));
把(Character.valueOf(E),Byte.valueOf((字节)14));
把(Character.valueOf(F),Byte.valueOf((字节)15));
}};
静态INT [] charValues = {0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1,-1,10, 11,第12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 ,10,11,12,13,14,15};
静态的char [] CS =新的char [] {'0','1','2','3','4','5','6','7','8','9' ,A,B,C,D,E,F,A,B,C,D,E,F};
公共静态无效的主要(字符串的args [])抛出异常{
很长一段时间= System.currentTimeMillis的();
的for(int i = 0; I< NUMBER_OF_RUNS;我++){
RES = getNumericValue(我);
}
的System.out.println(Character.getNumericValue:);
的System.out.println(System.currentTimeMillis的() - 时间);
时间= System.currentTimeMillis的();
的for(int i = 0; I< NUMBER_OF_RUNS;我++){
RES = getDigit(我);
}
的System.out.println(Character.digit将:);
的System.out.println(System.currentTimeMillis的() - 时间);
时间= System.currentTimeMillis的();
的for(int i = 0; I< NUMBER_OF_RUNS;我++){
尝试 {
RES = getValueFromArray(我);
}赶上(抛出:IllegalArgumentException E){
}
}
的System.out.println(阵列);
的System.out.println(System.currentTimeMillis的() - 时间);
时间= System.currentTimeMillis的();
的for(int i = 0; I< NUMBER_OF_RUNS;我++){
RES = getValueFromHashMap(我);
}
的System.out.println(HashMap的<性格,字节计算值:);
的System.out.println(System.currentTimeMillis的() - 时间);
时间= System.currentTimeMillis的();
的for(int i = 0; I< NUMBER_OF_RUNS;我++){
焦炭C = CS [我%cs.length]。
RES = getValueFromComputeMethod(C);
}
的System.out.println(JonSkeet直接法:);
的System.out.println(System.currentTimeMillis的() - 时间);
时间= System.currentTimeMillis的();
的for(int i = 0; I< NUMBER_OF_RUNS;我++){
RES = getValueFromSwitch(我);
}
的System.out.println(切换);
的System.out.println(System.currentTimeMillis的() - 时间);
}
私人静态字节getValueFromSwitch(int i)以{
字节水库;
焦炭CH = CS [我%cs.length]。
开关(CH){
情况下0:
RES = 0;
打破;
情况1':
RES = 1;
打破;
案2:
RES = 2;
打破;
案3:
RES = 3;
打破;
案4:
RES = 4;
打破;
案5:
RES = 5;
打破;
案6:
RES = 6;
打破;
案7:
RES = 7;
打破;
情况下8:
RES = 8;
打破;
案9:
RES = 9;
打破;
案一:
情况下A:
RES = 10;
打破;
案例'B':
案例'B':
RES = 11;
打破;
情况下C:
情况下C:
RES = 12;
打破;
情况下D:
情况下D:
RES = 13;
打破;
案E:
案E:
RES = 14;
打破;
案例'F':
案例'F':
RES = 15;
打破;
默认:
抛出新的RuntimeException(未知的十六进制字符:+ CH);
}
返回水库;
}
私人静态字节getValueFromComputeMethod(字符C){
字节的结果= 0;
如果(c取代; ='0'和;&安培;℃下='9')
{
结果=(字节)(三 - '0');
}
如果(C> ='A'和;和C< ='F')
{
结果=(字节)(C - 'A'+ 10);
}
如果(C> ='A'和;和C< =F)
{
结果=(字节)(C - 'A'+ 10);
}
返回结果;
}
私人静态字节getValueFromHashMap(int i)以{
返回map.get(Character.valueOf(CS [则i%cs.length])).byteValue();
}
私人静态字节getValueFromArray(int i)以{
焦炭C = CS [我%cs.length]。
如果(C<'0'|| c取代;'F'){
抛出新抛出:IllegalArgumentException();
}
字节的结果=(字节)charValues [C-'0'];
如果(水库℃,){
抛出新抛出:IllegalArgumentException();
}
返回结果;
}
私人静态字节getDigit(int i)以{
返程(字节)Character.digit将(CS [我%cs.length],16);
}
私人静态字节getNumericValue(int i)以{
返程(字节)Character.getNumericValue(CS [我%cs.length]);
}
}
解决方案
一个preinitialised阵列会比一个HashMap快。事情是这样的:
的 INT CharValues [f的 - '0'+ 1] = {0,1,2,3,4,5,6,7,8,9,-1, -1,... -1,10,11,12,...};
如果(C<'0'|| c取代;'F'){
抛出新抛出:IllegalArgumentException();
}
INT N = CharValues [C-'0'];
如果(正℃,){
抛出新抛出:IllegalArgumentException();
}
// N包含一个数字值
您应该基准,其他方法这个方法(如Jon飞碟双向的直接法)来确定,这将是最快的为您的应用程序。
I want to convert from char representing a hexadecimal value (in upper or lower case) to byte, like
'0'->0, '1' -> 1, 'A' -> 10, 'a' -> 10, 'f' -> 15 etc...
I will be calling this method extremely often, so performance is important. Is there a faster way than to use a pre-initialized HashMap<Character,Byte>
to get the value from?
Answer
It seems like it's a tossup between using a switch-case and Jon Skeet's direct computing solution - the switch-case solution seems to edge out ever so slightly, though. Greg's array method wins out. Here are the performance results (in ms) for 200,000,000 runs of the various methods:
Character.getNumericValue:
8360
Character.digit:
8453
HashMap<Character,Byte>:
15109
Greg's Array Method:
6656
JonSkeet's Direct Method:
7344
Switch:
7281
Thanks guys!
Benchmark method code
Here ya go, JonSkeet, you old competitor. ;-)
public class ScratchPad {
private static final int NUMBER_OF_RUNS = 200000000;
static byte res;
static HashMap<Character, Byte> map = new HashMap<Character, Byte>() {{
put( Character.valueOf( '0' ), Byte.valueOf( (byte )0 ));
put( Character.valueOf( '1' ), Byte.valueOf( (byte )1 ));
put( Character.valueOf( '2' ), Byte.valueOf( (byte )2 ));
put( Character.valueOf( '3' ), Byte.valueOf( (byte )3 ));
put( Character.valueOf( '4' ), Byte.valueOf( (byte )4 ));
put( Character.valueOf( '5' ), Byte.valueOf( (byte )5 ));
put( Character.valueOf( '6' ), Byte.valueOf( (byte )6 ));
put( Character.valueOf( '7' ), Byte.valueOf( (byte )7 ));
put( Character.valueOf( '8' ), Byte.valueOf( (byte )8 ));
put( Character.valueOf( '9' ), Byte.valueOf( (byte )9 ));
put( Character.valueOf( 'a' ), Byte.valueOf( (byte )10 ));
put( Character.valueOf( 'b' ), Byte.valueOf( (byte )11 ));
put( Character.valueOf( 'c' ), Byte.valueOf( (byte )12 ));
put( Character.valueOf( 'd' ), Byte.valueOf( (byte )13 ));
put( Character.valueOf( 'e' ), Byte.valueOf( (byte )14 ));
put( Character.valueOf( 'f' ), Byte.valueOf( (byte )15 ));
put( Character.valueOf( 'A' ), Byte.valueOf( (byte )10 ));
put( Character.valueOf( 'B' ), Byte.valueOf( (byte )11 ));
put( Character.valueOf( 'C' ), Byte.valueOf( (byte )12 ));
put( Character.valueOf( 'D' ), Byte.valueOf( (byte )13 ));
put( Character.valueOf( 'E' ), Byte.valueOf( (byte )14 ));
put( Character.valueOf( 'F' ), Byte.valueOf( (byte )15 ));
}};
static int[] charValues = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,10, 11, 12, 13,14,15};
static char[] cs = new char[]{'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','A','B','C','D','E','F'};
public static void main(String args[]) throws Exception {
long time = System.currentTimeMillis();
for( int i = 0; i < NUMBER_OF_RUNS; i++ ) {
res = getNumericValue( i );
}
System.out.println( "Character.getNumericValue:" );
System.out.println( System.currentTimeMillis()-time );
time = System.currentTimeMillis();
for( int i = 0; i < NUMBER_OF_RUNS; i++ ) {
res = getDigit( i );
}
System.out.println( "Character.digit:" );
System.out.println( System.currentTimeMillis()-time );
time = System.currentTimeMillis();
for( int i = 0; i < NUMBER_OF_RUNS; i++ ) {
try {
res = getValueFromArray( i );
} catch (IllegalArgumentException e) {
}
}
System.out.println( "Array:" );
System.out.println( System.currentTimeMillis()-time );
time = System.currentTimeMillis();
for( int i = 0; i < NUMBER_OF_RUNS; i++ ) {
res = getValueFromHashMap( i );
}
System.out.println( "HashMap<Character,Byte>:" );
System.out.println( System.currentTimeMillis()-time );
time = System.currentTimeMillis();
for( int i = 0; i < NUMBER_OF_RUNS; i++ ) {
char c = cs[i%cs.length];
res = getValueFromComputeMethod( c );
}
System.out.println( "JonSkeet's Direct Method:" );
System.out.println( System.currentTimeMillis()-time );
time = System.currentTimeMillis();
for( int i = 0; i < NUMBER_OF_RUNS; i++ ) {
res = getValueFromSwitch( i );
}
System.out.println( "Switch:" );
System.out.println( System.currentTimeMillis()-time );
}
private static byte getValueFromSwitch( int i ) {
byte res;
char ch = cs[i%cs.length];
switch( ch ) {
case '0':
res = 0;
break;
case '1':
res = 1;
break;
case '2':
res = 2;
break;
case '3':
res = 3;
break;
case '4':
res = 4;
break;
case '5':
res = 5;
break;
case '6':
res = 6;
break;
case '7':
res = 7;
break;
case '8':
res = 8;
break;
case '9':
res = 9;
break;
case 'a':
case 'A':
res = 10;
break;
case 'b':
case 'B':
res = 11;
break;
case 'c':
case 'C':
res = 12;
break;
case 'd':
case 'D':
res = 13;
break;
case 'e':
case 'E':
res = 14;
break;
case 'f':
case 'F':
res = 15;
break;
default:
throw new RuntimeException("unknown hex character: " + ch );
}
return res;
}
private static byte getValueFromComputeMethod( char c ) {
byte result = 0;
if (c >= '0' && c <= '9')
{
result = (byte)(c - '0');
}
if (c >= 'a' && c <= 'f')
{
result = (byte)(c - 'a' + 10);
}
if (c >= 'A' && c <= 'F')
{
result = (byte)(c - 'A' + 10);
}
return result;
}
private static byte getValueFromHashMap( int i ) {
return map.get( Character.valueOf( cs[i%cs.length] ) ).byteValue();
}
private static byte getValueFromArray( int i ) {
char c = cs[i%cs.length];
if (c < '0' || c > 'f') {
throw new IllegalArgumentException();
}
byte result = (byte)charValues[c-'0'];
if (res < 0) {
throw new IllegalArgumentException();
}
return result;
}
private static byte getDigit( int i ) {
return (byte)Character.digit( cs[i%cs.length], 16 );
}
private static byte getNumericValue( int i ) {
return (byte)Character.getNumericValue( cs[i%cs.length] );
}
}
解决方案
A preinitialised array would be faster than a HashMap. Something like this:
int CharValues['f'-'0'+1] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, ... -1, 10, 11, 12, ...};
if (c < '0' || c > 'f') {
throw new IllegalArgumentException();
}
int n = CharValues[c-'0'];
if (n < 0) {
throw new IllegalArgumentException();
}
// n contains the digit value
You should benchmark this method against other methods (such as Jon Skeet's direct method) to determine which will be the fastest for your application.
上一篇:借鉴螺旋等距点螺旋