5
\$\begingroup\$

I want to visually inspect all the characters that Java thinks are in any given UnicodeBlock. The following method, as far as I can tell, does the task. But, it sure feels like awful design.

public static void displayUnicodeBlock(Character.UnicodeBlock block) {
    int maxCharVal = (int) Math.pow(2, 16);
    for(int cInt = 0; cInt <= maxCharVal; cInt++) {
        char c = (char) cInt;           
        if(Character.UnicodeBlock.of(c) == block) { 
            System.out.println("_" + c + "_");
        }
    }
}
  • Would reflection be the ideal solution?
  • Can reflection actually show every character in a UnicodeBlock? How?
  • My solution is stupid because it is inefficient?
  • My solution is stupid because it is hardwired with 2^16?
\$\endgroup\$

3 Answers 3

5
\$\begingroup\$

It is truly unfortunate that Character.UnicodeBlock doesn't have a min() and max(). In fact, the way it is implemented in OpenJDK is as a private static blockStarts table, which is entirely unhelpful to you.

I don't have a better solution, but rather a complication. The Java char type only covers the Basic Multilingual Plane. To be pedantic, you would need to cover even larger codepoints, with Character.UnicodeBlock.of(int)! (For example, Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B starts at U+20000, which cannot be encoded using a single char, and therefore iterating up to 216 would not find it.)

It appears that existing Unicode blocks have sizes that are multiples of 16, so you could take advantage of that instead of testing every single codepoint.

Code blocks are contiguous. Therefore, a possible optimization is that once you have found a character that is in the desired block, if you then encounter a character that is not in the block, then you're done.

\$\endgroup\$
2
  • \$\begingroup\$ With regard to your complication, does the range from 0 to Math.pow(2, Character.SIZE) cover every possible character that Java can represent? If not, then what does "Character.SIZE" mean? btw: the optimizations are very informative. thank you. \$\endgroup\$
    – red shoe
    Mar 5, 2015 at 18:53
  • \$\begingroup\$ Character.SIZE is just hard-coded to 16. However, some of the rarer Unicode characters have codepoints greater than 2^16 — they are said to be outside the Basic Multilingual Plane. \$\endgroup\$ Mar 16, 2015 at 19:44
2
\$\begingroup\$

The maxCharVal initializer can be replaced with 0xffff or the static value Character.MAX_VALUE. This removes the hard wire and the slow pow function.

\$\endgroup\$
1
\$\begingroup\$

Why use Math.Pow using constants? Replace it with 65,536.

\$\endgroup\$
2
  • 2
    \$\begingroup\$ "Math.Pow(2, 16)" is sort of self-documenting. Seeing "65536" is too unsettling. I've gotta focus just to see if it has 5 digits. \$\endgroup\$
    – red shoe
    Mar 5, 2015 at 18:59
  • 1
    \$\begingroup\$ @dwakam however 1 << 16 is still faster and also self-documenting (though admittedly to a lesser effect), either way my suggestion of Character.MAX_VALUE eliminates both and is fully self documenting. \$\endgroup\$ Mar 6, 2015 at 10:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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