从代码点整数列表生成字符串对象?
Posted
技术标签:
【中文标题】从代码点整数列表生成字符串对象?【英文标题】:Generate a String object from a List of code point integers? 【发布时间】:2021-10-06 21:36:16 【问题描述】:如果我有一个 List< Integer >
其整数值是 Unicode code point 数字。如何构造由这些代码点确定的字符的String
对象?
例如:
List < Integer > codePoints = List.of( 100, 111, 103, 128054 ) ;
… 或:
List < Integer > codePoints = "cat".codePoints().boxed().toList();
我如何从codePoints
获得另一个值为cat
的String
对象?
【问题讨论】:
好问题!正因为您使用了Stream#toList
,它可从 Java-16 获得,如果问题也被标记为 Java-16,它将对读者有用。
【参考方案1】:
List
➠ Stream
➠ StringBuilder
➠ String
一种解决方案是将您的List
转换为Stream
。然后将该流的元素收集到StringBuilder
中。 StringBuilder
类提供了一个 appendCodePoint
方法,专门用于容纳代码点整数。当可变的StringBuilder
完成后,转换为不可变的String
。
String output = codePoints.stream().collect( StringBuilder :: new , StringBuilder :: appendCodePoint , StringBuilder :: append ).toString();
或不同的格式:
String output =
codePoints
.stream()
.collect( StringBuilder :: new , StringBuilder :: appendCodePoint , StringBuilder :: append )
.toString();
这是一些示例代码。
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();
看到这个code run live at IdeOne.com。
输入:狗?
代码点:[100、111、103、128054]
输出:狗?
要了解带有StringBuilder
方法引用的代码是如何工作的,请参阅Java 8 Int Stream collect with StringBuilder。
为方便起见,我们可以为这段代码创建一个实用方法。为了安全起见,我们可以添加对.filter
的调用以跳过any invalid code point 号码(负数或超出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 ;
看到code run live at IdeOne.com。
【讨论】:
your - 你不是说my吗?我一定是错过了什么。 @rzwitserloot 我不明白你的意思。 你在回答你自己的问题。 @rzwitserloot 是的,我以第二人称回答我自己的问题,以免分散读者的注意力。我写了问题和答案的事实是无关紧要的。我不知道你为什么会在意。【参考方案2】:String
has a constructor 接受 int
代码点编号的数组。
int[] ints = codePoints.stream().mapToInt(i -> i).toArray();
String string = new String(ints, 0, ints.length);
转换List
-> Stream
-> IntStream
-> int[]
-> String
【讨论】:
我不知道这个隐藏的宝藏,尽管它从 Java-5 开始就有了。【参考方案3】:现有的答案很好,但也有一种简单的“老式”方法,不需要使用函数式接口或流。这是最小且完整的示例代码:
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());
当代码运行时,输出如下:
sb=d▮og?
注意事项:
输出中的黑色矩形表示示例数据中故意包含的无效代码点。 静态方法Character.toString(int codePoint)
需要JDK 11或更高版本。
可能需要更改字体才能正确呈现输出。我使用了 Segoe UI 符号。
如果考虑并行操作,显然使用基于流的方法是可行的方法,但对于不关心性能和可伸缩性的场景,可以说简单的方法同样好。
【讨论】:
以上是关于从代码点整数列表生成字符串对象?的主要内容,如果未能解决你的问题,请参考以下文章