The hardly known MessageFormat

· JavaPerformance

I wonder how many people actually know about java.text.MessageFormat. I didn't until a few days ago, and it's a shame, in my opinion. In Java 5.0, we were introduced with a new feature which was the new String.format method, with the complimentary PrintStream.printf method (classically used via the System.out member). This feature allowed us to go back to the old C days, and write things like String.format("The index is %d", idx) instead of the old, familiar System.out.print("The index is " + idx). Obviously, better uses for this method have been found. However, the MessageFormat class provided this functionality, even if in a bit more complicated manner, years ago. Getting to know MessageFormat I found out that:
  • It's faster For a simple format, such as "The index is X and the letter is Y" where X was some loop index and Y was the character achieved by 'a' + (X % 26), MessageFormat.format worked about three times faster than String.format.
  • It's bi-directional With a complimentary MessageFormat.parse method, you could extract the same parameters you use for formatting from an already formatted text.
  • Optional choice formatting Inside the format pattern you can define conditions that would show different values relevant to the value passed. For example, you could show "no entries" if the value passed was 0, and "X entries" if the value passed was higher, by just writing {0, choice, "0#no entries|0< {0} entries"} as a format pattern. Obviously, there's a class externalising this behaviour called ChoiceFormat.
Give it a try. In my opinion, it's very useful when one needs to generate the same patterned text for different values in some iteration or at a triggered event - patterned text such as SQL code or log messages. Edited: removed the SQL code generation. As noted in the comments, it's better to use PreparedStatement instead.

Comments (8)

Moritz
I use it all the time. It is very useful for generating formatted CSV files. But regarding SQL, why don't you use the PreparedStatement?
Avah
It's true. Using PreparedStatement is much better. I wrote it really late. :)
Manpreet
Sounds like you never cared/needed to I18nize/L10nize your code ;)
Avah
Never in my life. :) I was always more concerned about Hebrew and right to left orientations (which are never good enough). I would like to hear more - Does MessageFormat allow for what you described, or is that the Stirng.format work?
Neil Weber
Well, for I18n, you put your labels, headers, messages, etc in a ResourceBundle. These strings are in the MessageFormat format. Thus you can easily plugin parameters. For example, the message might be "The '{0}' attribute must be between {1} and {2}." In another language, it might look like this "fdjk {1} jdfd {2}, fdfd jfkdjf {0}." Your code doesn't care.
Shai Almog
I have a funny message format story... In the late 90's I was working for a company that needed to localize their C++ application to Hebrew. The engineer responsible of this task approached me for advice and I explained in great detail the wonders of MessageFormat. So we built a tool similar for the message format in order to localize a particular (rather complex) area of the application and all was well. A year or so passed (still the 90's) that guy was long gone and I was tasked with rewriting his code that was "too complex"... Turns out he didn't comment anything and the only person who knew why he chose to implement everything with an external resource file was me (and I forgot completely I have terrible memory). Once I looked over the code I remembered everything and explained the logic to the project lead who got all excited about this. Since I had the time allocated already I built on his feature and made quite a few aditional improvements and commented like crazy, then I resigned (to start my own consulting firm). A year later I came over to visit and one of the new guys dumped everything we did because it was "too complex", when I asked if he read the comments "he didn't bother"... Lesson learned: Build a better mouse trap and most people won't understand what it is. Put a huge sign on top: "BETTER MOUSE TRAP" and still no one will care.
Avah
That's just crazy, Shai. Usually old code will find itself on its way to the trash unless there's some enthusiastic "old-code" team leader or prominent member, or if the writer of that code is still in the firm. That's my own experience, anyway. I do understand now the localisation issues. Nice idea... Glad to hear it Before I enter a localisation problem. :)
3bit
I guess the performance penality can be explained when looking at the String.format code in the JDK: public static String format(String format, Object ... args) { return new Formatter().format(format, args).toString(); } So using a local Formatter might improve things.