Tag Archives: string concatenation

Primitive types to String conversion and String concatenation

by Mikhail Vorontsov

Primitive types to String conversion

From time to time you may need to create a string in your program from several values, some of them may be of primitive types. If you have two or more primitive type values in the beginning of your string concatenation, you need to explicitly convert first of them to a string (otherwise System.out.println( 1 + 'a' ) will print ’98’, but not ‘1a’). Of course, there is a family of String.valueOf methods (or corresponding wrapper type methods), but who needs them if there is another way which requires less typing?

Concatenating an empty string literal and the first of your primitive type variables (in our example, "" + 1) is the easiest idea. Result of this expression is a String and after that you can safely concatenate any primitive type values to it – compiler will take care of all implicit conversions to String.

Unfortunately, this is the worst way one can imagine. In order to understand why it is so, we need to review how string concatenation operator is translated in Java. If we have a String value (doesn’t matter which sort of it – literal or variable or method call) followed by + operator followed by any type expression:

1
string_exp + any_exp
string_exp + any_exp

Java compiler will translate it to:

1
new StringBuilder().append( string_exp ).append( any_exp ).toString()
new StringBuilder().append( string_exp ).append( any_exp ).toString()

If you have more than one + operator in the expression, you will end up with several StringBuilder.append calls before final toString call.

Continue reading

Use case: FIX messages processing. Part 2: writing and optimizing a FIX gateway

by Mikhail Vorontsov

Now, having a fast parsing method from the first part of this article, let’s try to implement a FIX gateway. Its purpose is to filter out some messages based on a some criteria. We wouldn’t discuss filtering in this article – it is very straightforward and very task-dependent. Instead we will see what we can do in order to optimize the gateway processing loop. For the beginning, let’s suppose that it is “parse-filter-compose message” loop. We have a parser, you have written a filter, now we need a compose method, which takes a list of parsed fields and returns a message string.

The following method uses a StringBuilder with initial size of 1024 bytes (it makes sense to use either average or maximal message length for StringBuilder initialization) to compose a message. It is rather straightforward, but contains a problem with double values: if values are big enough, they will be formatted in scientific “e”-notation, which means that we will not get an original message. Though, depending on the gateway clients, it may not be a problem – general purpose double parsers support scientific notation. You can read more about double -> String -> double conversion in BigDecimal vs double article.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//compose a message from a list of parsed fields
private static String compose( final List<Field> fields )
{
    boolean first = true;
    final StringBuilder sb = new StringBuilder( 1024 );
    for ( final Field fld : fields )
    {
        if ( first )
            first = false;
        else
            sb.append( FIELD_SEPARATOR_CHAR );
        sb.append( fld.id ).append( VALUE_SEPARATOR_CHAR );
        if ( DATE_FIELDS.get( fld.id ) )
            sb.append( DATE_FORMAT.get().format( fld.value ) );
        else if ( INT_FIELDS.get( fld.id ) )
            sb.append( Integer.toString( ( Integer ) fld.value ) );
        else if ( DOUBLE_FIELDS.get( fld.id ) )
            sb.append( Double.toString( ( Double ) fld.value ) );
        else
            sb.append( fld.value );
    }
    return sb.toString();
}
//compose a message from a list of parsed fields
private static String compose( final List<Field> fields )
{
    boolean first = true;
    final StringBuilder sb = new StringBuilder( 1024 );
    for ( final Field fld : fields )
    {
        if ( first )
            first = false;
        else
            sb.append( FIELD_SEPARATOR_CHAR );
        sb.append( fld.id ).append( VALUE_SEPARATOR_CHAR );
        if ( DATE_FIELDS.get( fld.id ) )
            sb.append( DATE_FORMAT.get().format( fld.value ) );
        else if ( INT_FIELDS.get( fld.id ) )
            sb.append( Integer.toString( ( Integer ) fld.value ) );
        else if ( DOUBLE_FIELDS.get( fld.id ) )
            sb.append( Double.toString( ( Double ) fld.value ) );
        else
            sb.append( fld.value );
    }
    return sb.toString();
}

Continue reading