Converter um número inteiro em uma representação de string hexadecimal em Java

Sep 17 2020

Eu lancei meu próprio método Java para converter ints em hexadecimal Strings:

import java.util.Arrays;
import java.util.Random;

public class Main {
    
    /**
     * Converts the input integer into its textual hexadecimal representation.
     * 
     * @param a the integer to convert.
     * @return the string representing {@code a} in hexadecimal notation.
     */
    public static String intToHexString(int a) {
        StringBuilder stringBuilder = new StringBuilder(Integer.BYTES * 2);
        boolean inLeadingZeros = true;
        
        while (a != 0) {
            char digit = toHexChar(a & 0xf);
            a >>>= 4;
            
            if (inLeadingZeros) {
                if (digit != 0) {
                    inLeadingZeros = false;
                    stringBuilder.append(digit);
                }
            } else {
                stringBuilder.append(digit);
            }
        }
        
        if (inLeadingZeros) {
            return "0";
        }
        
        return stringBuilder.reverse().toString();
    }
    
    // Converts the integer digit to its textual hexadecimal representation:
    private static char toHexChar(int digit) {
        return digit >= 0 && digit < 10 ? 
                (char)(digit + '0') :
                (char)(digit - 10 + 'a');
    }
    
    private static final int ITERATIONS = 10_000_000;
    private static final int WARMUP_ITERATIONS = 10_000_000;
    
    private static void warmup() {
        System.out.println("Warming up...");
        Random random = new Random();
        
        for (int i = 0; i < WARMUP_ITERATIONS; i++) {
            int a = random.nextInt();
            intToHexString(a);
            Integer.toHexString(a);
        }
        
        System.out.println("Warming up done.");
    }
    
    private static void benchmark() {
        long seed = System.nanoTime();
        Random random = new Random(seed);
        System.out.println("Seed = " + seed);
        
        int[] inputArray = new int[ITERATIONS];
        String[] outputArray1 = new String[inputArray.length];
        String[] outputArray2 = new String[inputArray.length];
        
        for (int i = 0; i < inputArray.length; i++) {
            inputArray[i] = random.nextInt();
        }
        
        // Benchmarking intToHexString:
        long startTime = System.nanoTime();
        
        for (int i = 0; i < ITERATIONS; i++) {
            outputArray1[i] = intToHexString(inputArray[i]);
        }
        
        long endTime = System.nanoTime();
        
        System.out.println(
                "intToHexString in " + 
                        ((endTime - startTime) / 1000_000) +
                        " milliseconds.");
        
        // Benchmarking Integer.toHexString:
        startTime = System.nanoTime();
        
        for (int i = 0; i < ITERATIONS; i++) {
            outputArray2[i] = Integer.toHexString(inputArray[i]);
        }
        
        endTime = System.nanoTime();
        
        System.out.println(
                "Integer.toHexString in " + 
                        ((endTime - startTime) / 1000_000) + 
                        " milliseconds.");
        
        System.out.println("Methods agree: " + Arrays.equals(outputArray1,
                                                             outputArray2));
    }
    
    public static void main(String[] args) {
        warmup();
        benchmark();
    }
}

Saída de amostra Warming up... Warming up done. Seed = 1290249323142300 intToHexString in 1041 milliseconds. Integer.toHexString in 562 milliseconds. Methods agree: true

Pedido de crítica

Por favor, diga-me tudo o que vier à mente.

Respostas

4 JoopEggen Sep 17 2020 at 18:42
  • emLeadingZeros eu acho duvidoso; nome errado provavelmente
  • 0x00_00_03_44 seria emitido como "344", enquanto o convencional seria um "0344" duplo (ou mesmo intercalado como "03 44"). A razão pela qual da esquerda para a direita pode-se criar um byte por dois caracteres.
  • O caso excepcional provavelmente pode ser tratado antecipadamente.
  • O erro if (digit != 0) {deve ser if (digit != '0') {ou algo mais é significado.
  • toHexChar ainda espera um dígito interno 0..10. Portanto, provavelmente um conflito semântico.
  • apois o nome do parâmetro é lamentável, especialmente em inglês; numou né mais claro.

Não tenho certeza se o seu código está correto apenas lendo-o, devido à variável & if.

/**
 * Converts the given integer into its textual hexadecimal representation.
 * 
 * @param num the integer to convert.
 * @return the string representing {@code num} in hexadecimal notation.
 */
public static String intToHexString(int num ) {
    if (num == 0) {
        return "00";
    }
    
    StringBuilder stringBuilder = new StringBuilder(Integer.BYTES * 2);
    while (num != 0) {
        char digit = toHexChar(num & 0xf);
        num >>>= 4;
        stringBuilder.append(digit);

        digit = toHexChar(num & 0xf);
        num >>>= 4;
        stringBuilder.append(digit);
    }
    return stringBuilder.reverse().toString();
}

// Converts the integer digit to its textual hexadecimal representation:
private static char toHexChar(int digit) {
    return 0 <= digit && digit < 10 ? 
            (char)(digit + '0') :
            (char)(digit - 10 + 'a');
}