String Operations with Java Streams

1. Overview

Java 8 has introduced a new Stream API that lets us process data in a declarative manner.

In this quick article, we would learn how to use the Stream API to split a comma-separated String into a list of Strings and how to join a String array into a comma-separated String.

We’ll also look at how to convert a string array to map using Stream API.

Nearly all of the time we face situations, where we need to iterate some Java Collections and filter the Collection based on some filtering logic. In a traditional approach for this type of situation, we would use lots of loops and if-else operations to get the desired result.

If you want to read more about the Stream API, check this article.

2. Joining Strings With the Stream API

Let’s use the Stream API to create a function which would join a String array into a comma-separated String:

public static String join(String[] arrayOfString){
    return Arrays.asList(arrayOfString)
      .stream()
      //.map(...)
      .collect(Collectors.joining(","));
}

Points to note here:

  • The stream() function converts any Collection into a stream of data
  • map() function is used to process the data
  • There is also another function, named filter(), where we can include filtering criteria

There can be scenarios, where we may want to join a String with some fixed prefix and postfix. With the Stream API we can do that in the following way:

public static String joinWithPrefixPostfix(String[] arrayOfString){
    return Arrays.asList(arrayOfString)
      .stream()
      //.map(...)
      .collect(Collectors.joining(",","[","]"));
}

As we can see in the Collectors.joining() method, we are declaring our prefix as ‘[‘ and postfix as ‘]’; hence the generated String will be created with declared […..] format.

3. Splitting Strings With Stream API

Now, let’s create a function, which would split a comma separated String into a list of String using Stream API:

public static List<String> split(String str){
    return Stream.of(str.split(","))
      .map (elem -> new String(elem))
      .collect(Collectors.toList());
}

It’s also possible to directly convert a String to a Character list using the Stream API:

public static List<Character> splitToListOfChar(String str) {
    return str.chars()
      .mapToObj(item -> (char) item)
      .collect(Collectors.toList());
}

One interesting fact to note here is that the chars() method converts the String into a stream of Integer where each Integer value denotes the ASCII value of each and every Char sequence. That’s why we need to explicitly typecast the mapper object in the mapToObj() method.

4. String Array to Map With Stream API

We can also convert a String array to map using split and Collectors.toMap, provided each item in the array contains a key-value entity concatenated by a separator:

public static Map<String, String> arrayToMap(String[] arrayOfString) {
	return Arrays.asList(arrayOfString)
	  .stream()
	  .map(str -> str.split(":"))
	  .collect(toMap(str -> str[0], str -> str[1]));
}

Here, “:” is the key-value separator for all the elements in String array.

Please remember that in order to avoid compilation error, we need to ensure that code is compiled using Java 1.8. To do this, we need to add the following plugin in the pom.xml:

<build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.3</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
    </plugins>        
</build>

5. Testing

Since we are done creating the functions, let’s create test cases to verify the outcome.

First, let’s test our simple joining method:

@Test
public void givenArray_transformedToStream_convertToString() {
    String[] programmingLanguages = {"java", "python", "nodejs", "ruby"};
    String expectation = "java,python,nodejs,ruby";

    String result  = JoinerSplitter.join(programmingLanguages);
    assertEquals(result, expectation);
}

Next, let’s create another one to test our simple splitting functionality:

@Test
public void givenString_transformedToStream_convertToList() {
    String programmingLanguages = "java,python,nodejs,ruby";

    List<String> expectation = new ArrayList<>();
    expectation.add("java");
    expectation.add("python");
    expectation.add("nodejs");
    expectation.add("ruby");

    List<String> result  = JoinerSplitter.split(programmingLanguages);

    assertEquals(result, expectation);
}

Finally, let’s test our String array to map functionality:

@Test
public void givenStringArray_transformedToStream_convertToMap() {

    String[] programming_languages = new String[] {"language:java","os:linux","editor:emacs"};
    
    Map<String,String> expectation=new HashMap<>();
    expectation.put("language", "java");
    expectation.put("os", "linux");
    expectation.put("editor", "emacs");
    
    Map<String, String> result = JoinerSplitter.arrayToMap(programming_languages);
    assertEquals(result, expectation);
    
}

In the same way, we need to create the rest of the test cases.

6. Conclusion

Stream API provides us with sophisticated data processing techniques. This new way of writing code is very efficient in terms of heap memory management in a multi-threaded environment.

Like always, the full source code is available over on Github.

Related posts:

Phương thức forEach() trong java 8
Sort a HashMap in Java
Java 8 Stream findFirst() vs. findAny()
Guide to WeakHashMap in Java
Spring Security 5 – OAuth2 Login
The Dining Philosophers Problem in Java
Concurrent Test Execution in Spring 5
The DAO with JPA and Spring
Dynamic Proxies in Java
Java Program to Find the Shortest Path from Source Vertex to All Other Vertices in Linear Time
Java Program to Implement Hash Tables
Java Program to Perform Sorting Using B-Tree
REST Pagination in Spring
Kiểu dữ liệu Ngày Giờ (Date Time) trong java
Java Program to Implement the Monoalphabetic Cypher
Spring Boot - Apache Kafka
Mệnh đề if-else trong java
Chuyển đổi Array sang ArrayList và ngược lại
Java Program to Implement the Schonhage-Strassen Algorithm for Multiplication of Two Numbers
Java Program to Implement ArrayList API
Java Program to Apply Above-Below-on Test to Find the Position of a Point with respect to a Line
Java Program to Find Strongly Connected Components in Graphs
Java Program to Implement a Binary Search Algorithm for a Specific Search Sequence
Java Program to Check whether Undirected Graph is Connected using DFS
Java Program to Implement Johnson’s Algorithm
Java Program to Implement Hash Tables Chaining with List Heads
Java Program to Perform Partition of an Integer in All Possible Ways
Spring Boot - Cloud Configuration Client
A Quick Guide to Spring MVC Matrix Variables
Chương trình Java đầu tiên
Java Program to Implement Slicker Algorithm that avoids Triangulation to Find Area of a Polygon
Rest Web service: Filter và Interceptor với Jersey 2.x (P2)