3

I have the following Java code that increases the value of a hex value and returns a string using the following format (where x is an increasing hex value and 7 is a literal):

xxxx-7xxx-xxxx

The value is increasing from left to right like so and consists of 12 characters:

0000-7000-0001
0000-7000-0002
...
0000-7fff-ffff
0001-7000-0000

The code:

public class GeneratorTemplate {
    private static final AtomicLong COUNTER = new AtomicLong(0);

    public static String generateTemplate() {
        // incrementing the counter
        long currentValue = COUNTER.getAndIncrement();

        // get 11 character (not 12 because 7 is a literal and appended) hex value represented as string
        String rawResult = String.format("%011X", currentValue & 0xFFFFFFFFFFFL);

        // append and format values
        return (rawResult.substring(0, 4) +
                "-7" +
                rawResult.substring(4, 7) +
                "-" +
                rawResult.substring(7)).toLowerCase();

    }

    public static void main(String[] args) {
        for (int i = 0; i < 3; i++) {
            System.out.println(generateTemplate());
        }
    }
}

It works but I'm sure that this is not efficient.

The performance issue revolves around the fact that I do appending of 7, hyphens and lowercase manually. I think that if I do this in the format() method, I'll have gains in performance. In addition, that code would be clearer

I tried to accomplish this in one line but to no avail. This code is obviously incorrect and I wonder how to use the format() method correctly, so that I won't have to append anything manually:

return String.format("%04X-7%03X-%04X", currentValue & 0xFFFFL, currentValue & 0xFFFL, currentValue & 0xFFFFL);

Could anyone clarify of whether this is possible to do using the format() method and what the number of F represents in the parameter (I obviously understand that this is hex but how many F's should be there)?

Thanks

11
  • 3
    Two questions about " I'm sure that this is not efficient.": 1.) why? Have you measured it in some structured way? 2.) even if it's "not efficient", are you sure that this matters? Do you generate these frequently enough that this code is likely to be the bottleneck? Commented May 23 at 11:17
  • In the scheme of things does efficiency for this really matter? And what would you expect the increase in efficiency to be?
    – WJS
    Commented May 23 at 11:18
  • "I'm sure that this is not efficient." How are you so sure? Did you measure its performance?
    – Sweeper
    Commented May 23 at 11:18
  • The question about performance has to do with the fact that hex is actually derived from a long value. I'm going to edit the question now
    – Joe D
    Commented May 23 at 11:20
  • 1
    You might try avoiding concatenation: public static String generateTemplate() {long currentValue = COUNTER.getAndIncrement();StringBuilder sb = new StringBuilder(String.format("%012x", currentValue & 0xFFFFFFFFFFFL));sb.setCharAt(4, '7');sb.insert(4, '-');sb.insert(9, '-');return sb.toString();}
    – g00se
    Commented May 23 at 12:42

2 Answers 2

4

use the String.format() method, so you can format the hex value directly without having to manually append the segments. You need to use the correct bit manipulation and formatting within String.format().

import java.util.concurrent.atomic.AtomicLong;

public class GeneratorTemplate {
    private static final AtomicLong COUNTER = new AtomicLong(0);

    public static String generateTemplate() {
        // Increment the counter
        long currentValue = COUNTER.getAndIncrement();

        // Use bit manipulation and formatting to generate the desired output
        long part1 = (currentValue >> 28) & 0xFFFF;  // First 4 hex digits
        long part2 = (currentValue >> 16) & 0xFFF;   // Next 3 hex digits
        long part3 = currentValue & 0xFFFF;          // Last 4 hex digits

        return String.format("%04X-7%03X-%04X", part1, part2, part3);
    }

    public static void main(String[] args) {
        for (int i = 0; i < 3; i++) {
            System.out.println(generateTemplate());
        }
    }
}

Bit Manipulation:

(>>): moves bits to the right, discarding bits on the right and filling the left side with zeros for unsigned shifts.

First Part: part1 = (currentValue >> 28) & 0xFFFF,shifts currentValue right by 28 bits to extract the first 4 hex digits.

The mask 0xFFFF ensures exactly 4 hex digits are taken. Second Part: part2 = (currentValue >> 16) & 0xFFF,shifts currentValue right by 16 bits to extract the next 3 hex digits.

The mask 0xFFF ensures exactly 3 hex digits are taken. Third Part: part3 = currentValue & 0xFFFF uses the mask 0xFFFF to get the last 4 hex digits directly.

Formatting:

 String.format("%04X-7%03X-%04X", part1, part2, part3)

%04X formats the first part to 4 hex digits.

%03X formats the middle part to 3 hex digits.

%04X formats the last part to 4 hex digits.

the out put of aforementioned code is:

output

4
  • 1
    You've not extracted the length and set of digits. eg test long currentValue = 0xBA987654321L
    – DuncG
    Commented May 23 at 11:53
  • 1
    i chnaged my answer: for your example would be BA98-7765-4321 Commented May 23 at 14:01
  • Thank you The only question left is how did you find out the number of bits to shift?
    – Joe D
    Commented May 24 at 6:56
  • 1 hex digit is 4 bits, why do we shift 28 instead of 16 bits?
    – Joe D
    Commented May 24 at 7:41
2

Well, the bit masking and shifting in Shila Mosammami's answer is probably the way to go. But in your earlier example, you called toLowerCase() after constructing the formatted value. But you don't need to do that. Just use:

String rawResult = String.format("%011x", v);

The lower case x in the format specifier says to use lower case values for the hex digits a-f.

Not the answer you're looking for? Browse other questions tagged or ask your own question.