2

If I have a List< Integer > whose integer values are Unicode code point numbers. How do I construct a String object of characters determined by those code points?

For example:

List < Integer > codePoints = List.of( 100, 111, 103, 128054 ) ;

… or:

List < Integer > codePoints = "cat".codePoints().boxed().toList();

How do I get another String object with value cat from codePoints?

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • Good question! Just because you have used, `Stream#toList`, which is available from Java-16, it will be useful to the readers if the question is tagged to Java-16 as well. – Arvind Kumar Avinash Oct 06 '21 at 06:41

3 Answers3

4

String has a constructor that takes an array of int code point numbers.

int[] ints = codePoints.stream().mapToInt(i -> i).toArray();
String string = new String(ints, 0, ints.length);

Converts List -> Stream -> IntStream -> int[] -> String

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Donald Raab
  • 6,458
  • 2
  • 36
  • 44
1

ListStreamStringBuilderString

One solution is to convert your List into a Stream. Then collect the elements of that stream into a StringBuilder. The StringBuilder class offers an appendCodePoint method specifically to accommodate code point integer numbers. When the mutable StringBuilder is complete, convert to an immutable String.

String output = codePoints.stream().collect( StringBuilder :: new , StringBuilder :: appendCodePoint , StringBuilder :: append ).toString();

Or different formatting:

String output = 
        codePoints
                .stream()
                .collect( StringBuilder :: new , StringBuilder :: appendCodePoint , StringBuilder :: append )
                .toString();

Here is some example code.

String input = "dog" ;
List < Integer > codePoints = input.codePoints().boxed().collect( Collectors.toList() );  // In Java 16+, replace the last part with simply `.toList()`.
String output = 
        codePoints
                .stream()
                .collect( StringBuilder :: new , StringBuilder :: appendCodePoint , StringBuilder :: append )
                .toString();

See this code run live at IdeOne.com.

input: dog

codePoints: [100, 111, 103, 128054]

output: dog

To understand how that code with StringBuilder method references works, see Java 8 Int Stream collect with StringBuilder.

We could make a utility method of this code, for convenience. For safety, we could add a call to .filter to skip any invalid code point number (either negative or beyond Character.MAX_CODE_POINT).

public static final String listOfCodePointsToString( List< Integer > codePoints )
{
    String output = 
            codePoints
                    .stream()
                    .filter( codePoint -> Character.isValidCodePoint​( codePoint ) )
                    .collect( StringBuilder :: new , StringBuilder :: appendCodePoint , StringBuilder :: append )
                    .toString();
    return output ;
}

See that code run live at IdeOne.com.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
0

The existing answers are fine, but there is also a simple "old fashioned" approach that doesn't require the use of functional interfaces or streams. Here's minimal and complete sample code:

package cp2string;

import java.util.List;

public class CP2String {

    public static void main(String[] args) {
        List< Integer> codePoints = List.of(100, -999, 111, 103, 128054);
        Character BLACK_VERTICAL_RECTANGLE = '\u25AE';
        StringBuilder sb = new StringBuilder();

        for (int cp : codePoints) {
            sb.append(Character.toString(Character.isValidCodePoint(cp) ? cp : BLACK_VERTICAL_RECTANGLE));
        }
        System.out.println("sb=" + sb.toString());
    }
}

When the code is run this is the output:

sb=d▮og

Notes:

  • The black rectangle in the output represents an invalid code point that was deliberately included in the sample data.
  • JDK 11 or later is required for the static method Character.toString​(int codePoint).
  • A font change may be needed to properly render the output. I used Segoe UI Symbol.
  • Obviously using a stream based approach is the way to go if parallel operations are a consideration, but for scenarios where performance and scalability are not concerns, a simple approach is arguably just as good.
skomisa
  • 16,436
  • 7
  • 61
  • 102