DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Writing DTOs With Java8, Lombok, and Java14+
  • Formatting Strings in Java: String.format() Method
  • Hibernate Validator vs Regex vs Manual Validation: Which One Is Faster?
  • Functional Approach To String Manipulation in Java

Trending

  • Power BI Embedded Analytics — Part 2: Power BI Embedded Overview
  • How the Go Runtime Preempts Goroutines for Efficient Concurrency
  • Streamlining Event Data in Event-Driven Ansible
  • Mastering Fluent Bit: Installing and Configuring Fluent Bit on Kubernetes (Part 3)
  1. DZone
  2. Coding
  3. Java
  4. Concatenating Strings in Java 8

Concatenating Strings in Java 8

This walkthrough of string concatenation explores the additions Java 8 made as well as how to use it with relatively new classes, like Optional.

By 
Daniela Kolarova user avatar
Daniela Kolarova
DZone Core CORE ·
Aug. 08, 17 · Tutorial
Likes (39)
Comment
Save
Tweet
Share
116.9K Views

Join the DZone community and get the full member experience.

Join For Free

Have you ever experienced the need to build a comma separated list of values from a list or an array in Java or building a file path using concatenated folder names and a file path delimiter? Well, Java 8 has this written for you— and not to only reduce your development time or prevent the code from additional errors, but to let you write more readable and understandable code.

Imagine a simple situation where we want to build a comma separated list of values from a list like the one here:

List<String> commaSeparatedValues = Arrays.asList("value1", "value2", "value3");


Let's do it a bit differently and replace the comma symbol with a semicolon. What we did until Java 8 was iterate over the list and append using the well-known Java class StringBuilder, or StringBuffer based on the use case. Normally, the code is implemented in a separate utility method that has to be tested by a unit test in order to validate that it produces the right result — and also to keep the code coverage in a good state.

Well, Java 8 offers static methods as part of the String class definition intended exactly for this purpose:

List<String> valuesList = Arrays.asList("value1", "value2", "value3");

String commaSeparatedValues = String.join("; ", valuesList);

System.out.println(commaSeparatedValues);


>>Output: value1; value2; value3


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 important part of the method's contract is that the parameters passed can't be null and the method will throw a NullPointerException if the contract is violated — if one or both of the parameters is null.

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

String baseDirectory = "baseDir";
String subFolder = "subFolder";
String fileName = "fileName";

List<String> filePathParts = Arrays.asList(baseDirectory, subFolder, fileName);
File file = new File(String.join(File.separator, filePathParts));


All good so far, but what happens when the String's join method is called? It delegates the calls to a slightly more sophisticated class called StringJoiner, which in fact offers more than just concatenating strings with a parametrized 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.

If we want to use StringJoiner with a suffix and prefix, we will have to use it directly or wrapped by another class. People experienced with Java 8 Streams most probably know where we're going with this: 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. Imagine we have to build a file path to store files based on predefined folder names — but also using parametrized names like, for example, the file name must end up with a particular date, and one of the folders should have a parametrized name not defined during the initial initialization of the class responsible for constructing the full file path:

String suffix  = new SimpleDateFormat("yyyyMMdd").format(new Date());
String paramValue = "P";

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



>>Output: baseDir\subFolder\P\fileName20170804


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);


So far, we managed to build a list of concatenated values and a file path with only a few lines. What about converting Java objects to concatenated strings in order to persist them as rows in files? Here is our class that can be persisted using the same approach:

public class Person {

    private String name;
    private String address;
    private int age;

    public Person(String name, String address, int age) {
        this.name = name;
        this.address = address;
        this.age = age;
    }

    public String convertToRow(CharSequence delimiter) {
        return String.join(delimiter, Arrays.asList(name, address, String.valueOf(age)));
    }
}


And the usage of it will look like the following:

Person person = new Person("John Right", "London", 35);

System.out.println(person.convertToRow(","));


>>Output: John Right,London,35


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

The intent of this post was to show the Java 8 approach for string value concatenation and its usage in various use cases. We definitely wrote less code, we didn't need unit testing for the concatenation part, we were able to combine it with additional processing of elements to be concatenated, and we managed to implement a simple object's persistence with one row of code. For more complicated objects, the building of the list of values for persistence may be extracted to a separate method, allowing the use of various strategies for the object's field ordering and formatting.

Java (programming language) Strings

Opinions expressed by DZone contributors are their own.

Related

  • Writing DTOs With Java8, Lombok, and Java14+
  • Formatting Strings in Java: String.format() Method
  • Hibernate Validator vs Regex vs Manual Validation: Which One Is Faster?
  • Functional Approach To String Manipulation in Java

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!