将字符串拆分为字符串数组

我需要将一个 String 拆分成一个由单个字符串组成的数组。

例如,将“ cat”分开会得到数组“ c”、“ a”、“ t”

409844 次浏览
String str = "cat";
char[] cArray = str.toCharArray();

也许可以使用 for 循环遍历 String 内容,并使用 charAt方法按字符提取字符。

例如,结合使用 ArrayList<String>可以得到单个字符的数组。

"cat".toCharArray()

但如果你需要线

"cat".split("")

Edit: 它将返回一个空的第一个值。

"cat".split("(?!^)")

这将产生

Array [“ c”,“ a”,“ t”]

for(int i=0;i<str.length();i++)
{
System.out.println(str.charAt(i));
}

将 String 转换为由单个字符串组成的数组的一种有效方法是这样做:

String[] res = new String[str.length()];
for (int i = 0; i < str.length(); i++) {
res[i] = Character.toString(str.charAt(i));
}

但是,这并没有考虑到这样一个事实,即 String中的 char实际上可以表示 Unicode 代码点的一半。(如代码点不在 BMP 中)为了解决这个问题,你需要遍历代码点... ... 这是更复杂的。

这种方法将比使用 String.split(/* clever regex*/)更快,而且可能比使用 Java8 + 流更快。它可能比这更快:

String[] res = new String[str.length()];
int 0 = 0;
for (char ch: str.toCharArray[]) {
res[i++] = Character.toString(ch);
}

因为 toCharArray必须 收到字符到一个新的数组。

如果需要输入 基本多语言平面以外的字符(一些 CJK 字符,新的表情符号... ...) ,则不能使用诸如 "a💫b".split("(?!^)")之类的方法,因为它们会破坏这些字符(结果为 array ["a", "?", "?", "b"]) ,必须使用更安全的方法:

"a💫b".codePoints()
.mapToObj(cp -> new String(Character.toChars(cp)))
.toArray(size -> new String[size]);

总结一下其他的答案。

这适用于所有 Java 版本:

"cat".split("(?!^)")

这只适用于 Java8及以上版本:

"cat".split("")

如果原始字符串包含 补充 Unicode 字符,那么 split()将不起作用,因为它将这些字符分割成代理项对。为了正确处理这些特殊字符,这样的代码可以工作:

String[] chars = new String[stringToSplit.codePointCount(0, stringToSplit.length())];
for (int i = 0, j = 0; i < stringToSplit.length(); j++) {
int cp = stringToSplit.codePointAt(i);
char c[] = Character.toChars(cp);
chars[j] = new String(c);
i += Character.charCount(cp);
}

如果字符串包含代理项对,则 split("(?!^)")不能正常工作。应使用 split("(?<=.)")

String[] splitted = "花ab🌹🌺🌷".split("(?<=.)");
System.out.println(Arrays.toString(splitted));

产出:

[花, a, b, 🌹, 🌺, 🌷]

在我之前的回答中,我混淆了 JavaScript。

我同意需要注意 Java 字符串中的 Unicode 代理项对。这打破了像 String.length()这样的方法的意义,甚至是 Character的函数意义,因为它最终是一个技术对象,可能不能代表人类语言中的一个字符。

我实现了4个方法,将一个字符串分割成表示字符串的列表(String对应于 性格的人类含义)。这是比较的结果:

一行是由1000个任意选择的表情符号和1000个 ASCII 字符(1000倍于 <emoji><ascii>,总共2000个人类意义的“字符”)组成的 String

Comparison of different splitting methods

(放弃256及512条措施) enter image description here

实施方法:

  • CodePoint (java 11及以上版本)
    public static List<String> toCharacterStringListWithCodePoints(String str) {
if (str == null) {
return Collections.emptyList();
}
return str.codePoints()
.mapToObj(Character::toString)
.collect(Collectors.toList());
}
  • 经典
    public static List<String> toCharacterStringListWithIfBlock(String str) {
if (str == null) {
return Collections.emptyList();
}
List<String> strings = new ArrayList<>();
char[] charArray = str.toCharArray();
int delta = 1;
for (int i = 0; i < charArray.length; i += delta) {
delta = 1;
if (i < charArray.length - 1 && Character.isSurrogatePair(charArray[i], charArray[i + 1])) {
delta = 2;
strings.add(String.valueOf(new char[]{ charArray[i], charArray[i + 1] }));
} else {
strings.add(Character.toString(charArray[i]));
}
}
return strings;
}
  • 正则表达式
    static final Pattern p = Pattern.compile("(?<=.)");
public static List<String> toCharacterStringListWithRegex(String str) {
if (str == null) {
return Collections.emptyList();
}
return Arrays.asList(p.split(str));
}

附件(原始资料) :

codePoints;classic;regex;lines
45;44;84;256
14;20;98;512
29;42;91;1024
52;56;99;2048
87;121;174;4096
175;221;375;8192
345;411;839;16384
667;826;1285;32768
1277;1536;2440;65536
2426;2938;4238;131072