Wednesday, July 29, 2009

Binary literals in Java

Integer (byte, short, int or long) literals in Java can be expressed using one of the following three formats

int n08 = 052;
int n10 = 42;
int n16 = 0x2A;

Here all three variables represent the same number. There is no out-of-the-box binary presentation. Nevertheless, it is desirable sometimes to specify constants in easy readable binary form, for example for bit masks.

The answer from Ed Swangren works fine.

int n02 = Integer.parseInt("101010", 2);

Here is another example:
public final static long mask11 =
Long.parseLong("00000000000000000000100000000000", 2);

I used long instead of int and added the modifiers to clarify possible usage of the presentation as a bit mask. There are, though, two inconveniences with this approach.
  1. The direct typing of all those zeroes is error prone

  2. The result is not available in decimal or hex format at the time of development

I can suggest alternative approach
public final static long mask11 = 1L << 11;

This expression makes it obvious that the 11th bit is 1 (count starts from 0, from the right to the left); and when you hover mouse cursor, the tooltip
long YourClassName.mask11 = 4096 [0x1000]

appears in Eclipse. You can define more complicated constants like:
public final static long n02 = mask05 | mask03 | mask01;

or explicitly
public final static long n02 = (1L<<5)|(1L<<3)|(1L<<1);

The value of the variable n02 will still be available in Eclipse at development time.

Thursday, July 23, 2009

Homemade recipe

This is another example of how simple "homemade" approach significantly outperforms patented generic methods. How often you needed to convert byte array into String object and vice versa? The recommended methods always require the name of Charset. Since in my case the charset is always UTF-8, I hardcoded it.
When converting from byte array to String, something like following can be used:
final static String b2s_recommended(byte[] bb) {
    try {
        return new String(bb, 0, bb.length, "UTF-8");
    } catch(Exception ex) {
        throw new RuntimeException(ex.getMessage());
    }
}
   
   

When converting from String to byte array something like following can be used:
final static byte[] s2b_recommended(String s) {
    try {
        return s.getBytes("UTF-8");
    } catch(Exception ex) {
        throw new RuntimeException(ex.getMessage());
    }
}
   
   

Corresponding "homemade" methods that don't pretend to be generic, can look like following:
final static String b2s_homemade(byte[] bb) {
    char[] cc = new char[bb.length];
    for (int i = 0; i < bb.length; ++i) {
        cc[i] = (char) bb[i];
    }
    return new String(cc);
}
   
final static byte[] s2b_homemade(String s) {
    byte[] bb = new byte[s.length()];
    for (int i = 0; i < bb.length; ++i) {
        bb[i] = (byte) s.charAt(i);
    }
    return bb;
}
   

On my computer homemade b2s outperformed recommended one with factor of 4.2 . For the s2b the performance bust was 6.0 !