HomeJavaHow to Concatenate Strings in Java 8

How to Concatenate Strings in Java 8

Get 30 minute iPhone repair with Puls! Schedule your repair now!

Concatenate Strings in Java, is that what you all are searching up, or trying to build a comma separated list of values from an array or from a list in Java. Look no further as Java 8 has this written for you – not only to reduce your development but to write more readable and understandable code.

Let’s take a very simple problem where we want to build a comma separated values from a list just like the one below:


List<String> commaSeparatedValues = Arrays.asList("arrayValue1", "arrayValue2", "arrayValue3");

Let’s try replace the comma symbol with a semicolon. Until Java 8, what we used to do is iterate the list and append the values using the well-known Java class StringBuilder, or StringBuffer based on the use case. In a normal use case, we implement the code in a separate utility method which can tested using the unit test. This is done in order to validate that the method produces the right results – and also to keep the code coverage in a good state.


List<String> valuesList = Arrays.asList("ArrayValue#1", "ArrayValue#2", "ArrayValue#3");
String commaSeparatedValues = String.join("; ", valuesList);
System.out.println(commaSeparatedValues);



Output:
ArrayValue#1; ArrayValue#2; ArrayValue#3

Well, Java 8 offers static methods join as part of the String class definition.

The join method offers the convenience of not adding the delimiter at the end of the string as well. As a matter of fact, class String offers two join methods with the following signatures:

public static String join(CharSequence delimiter, CharSequence... elements)
public static String join(CharSequence delimiter, Iterable<? extends CharSequence> elements)

 

Furthermore, an most important part to remember is that the method’s contract doesn’t allow the parameters to be passed as null. If the contract is violated, i.e. if one or both the parameters are null, then the method will throw a NullPointerException.

Another simple use case is file path construction in Java, when we need to concatenate various folder names:

String baseFolder = "baseFolder";
String subFolder = "subFolder";
String fileName = "fileName";
List<String> filePaths = Arrays.asList(baseFolder, subFolder, fileName);
File file = new File(String.join(File.separator, filePaths));

 

So far it’s all good, but what exatly happens when we call the String’s join method? The method delegates the calls to a slightly more sophisticated class knows as StringJoiner. This class in fact offers more than just concatenating string with a parameterized delimiter. As the Javadoc states:

StringJoiner is used to construct a sequence of characters separated
by a delimiter and optionally starting with a supplied prefix
and ending with a supplied suffix.

Now the question arises how can we use suffix and prefix with StringJoiner? Well to answer this, we will have to use it directly or as a wrapper by another class. Experienced developers with Java 8 Streams most probably know where we’re going with this. Yes, you bet it right, the Collectors class:

public static Collector<CharSequence, ?, String> joining(CharSequence delimiter,
                                                         CharSequence prefix,
                                                         CharSequence suffix) {
    return new CollectorImpl<>(
        () -> new StringJoiner(delimiter, prefix, suffix),
        StringJoiner::add, StringJoiner::merge,
        StringJoiner::toString, CH_NOID);
}

 

Although the implementation of the method looks a bit complicated, using it with Java 8 Streams is pretty straightforward. Lets consider taking the example of building a file path as previous example based on predefined folder names – but also using parametrized names. For example, the file name must end up with a unique identification string, and one of the folders should have a parametrized name not defined during the initial initiallization of the class. This class is responsible for constructing the full file path:

String suffix  = "_dj1322";
String paramValue = "DJ";
List<String> filePathParts = Arrays.asList(baseFolder, subFolder, "%s", fileName);
String filePath = filePathParts.stream().map(value -> String.format(value, paramValue))
          .collect(Collectors.joining(File.separator, "", suffix));


Output: 
baseFolder\subFolder\DJ\fileName_dj1322

You have probably noticed that, for each element, we apply string-based formatting before joining the elements. This can also be done after the concatenated string was built:

String filePathFormatted = String.format(filePathParts.stream()
           .collect(Collectors.joining(File.separator, "", suffix)), paramValue);

Ok so far, we have managed to build a list of file paths using concatinating values with only few lines of code. Now let’s take a more example of converting Java objects to concatenated strings. These concatenated strings will be preserved as rows in files. Below is our sample class of Employee that can be persisted using the same approach.

public class Employee {
    private String name;
    private String address;
    private int employeeId;
    public Person(String name, String address, int employeeId) {
        this.name = name;
        this.address = address;
        this.employeeId = employeeId;
    }
    public String convertToRow(CharSequence delimiter) {
        return String.join(delimiter, Arrays.asList(name, address, String.valueOf(employeeId)));
    }
}

And the usage of it will look like the following:

Employee employeeObj = new Employee("Tom Hanks", "London", 020139);
System.out.println(employeeObj.convertToRow(","));

Output: 
Tom Hanks,London,020139

 

From a code design perspective, the persistence method might be placed in another class responsible for Employee’s persistence and provide more flexibility regarding column ordering and formatting in the form of persistence metadata.

Conclusion

This journal entry was written to showcase the Java 8 approach for string concatenation and its usage in various use cases. We managed to implement a simple object’s persistence with one row of code. For more complicated objects, the list of values which needs to be persisted may be extracted to a separate method. This allows the use of various strategies for the object’s field formatting and also for ordering up the objects data.

Get 30 minute iPhone repair with Puls! Schedule your repair now!

RELATED ARTICLES

Most Popular