Most of these suggestions apply only after a bottleneck has been identified:
Logically partition your strings into those that require internationalization support (i.e., text) and those that don't.
Avoid internationalization where the Strings never require it.
Avoid using the StreamTokenizer.
Regular expressions provide acceptable performance compared with using String searching methods and String character iteration tokenizing techniques.
Create and optimize your own framework to convert objects and primitives to and from strings.
Use efficient methods of String that do not copy the characters of the string, e.g., String.substring( ).
Avoid using inefficient methods of String that copy the characters of the string, e.g., String.toUppercase( ) and String.toLowercase( ).
Use the string concatenation operator to create Strings at compile time.
Use StringBuffers to create Strings at runtime.
Specify when the underlying char array is copied when reusing StringBuffers.
Improve access to the underlying String char array by copying the chars into your own array.
Manipulate characters in char arrays rather than using String and StringBuffer manipulation.
Reuse char arrays.
Optimize the string comparison and search algorithm for the data being compared and searched.
Compare strings by identity.
Convert a comparison task to a (hash) table lookup.
Handle case-insensitive comparisons differently from case-sensitive comparisons.
Apply the standard performance optimization for case-insensitive access (maintaining a second collection with all strings uppercased).
Use java.text.CollationKeys rather than a java.text.Collator object to sort international strings.
Use String.compareTo( ) for string comparison where internationalization is unnecessary.
Partially sort (international) strings using a simple comparison algorithm before using the full (internationalized) comparison.