Как в Java разбить на символы строку, содержащую некоторые эмодзи и другие символы UTF-16 (👏, 󰑼 и т.п.)

Многие символы UTF-16 представляют собой так называемые суррогатные пары. Такие пары в каком-то смысле являют собой сочетание двух символов. Поэтому, например, такой код:

String s = "👏👏";

for (char ch : s.toCharArray()) {

System.out.print(ch);

}

Выведет в консоль четыре вопросительных знака ????, по два на каждый символ. При этом отметим, что не со всеми эмодзи есть такая проблема.

Метод codePoints(), вызванный на строке, вернёт поток чисел, которые можно сгруппировать в массивы char[]. Для этого можно воспользоваться методом Character.toChars(int codePoint), который сам определит, является ли codePoint символа суррогатной парой и тогда каждый char[] будет состоять из двух элементов или это обычный символ и тогда он будет помещён в массив char[] из одного элемента.

Затем эти местами одинарные, местами парные массивы char'ов преобразовываются в строки. А строки уже можно собрать, например, в список:

static List<String> split(String text) {

return text.codePoints() //преобразуем строку в поток codePoint

.mapToObj(Character::toChars) //преобразуем поток codePoint в поток массивов char[]

.map(String::valueOf) //преобразуем поток char[] в поток строк

.collect(Collectors.toList()); //собираем строки в список

}

Также обратите внимание, что с точки зрения Java любая суррогатная пара — это по сути строка. И такой код, например, не откомпилируется:

char ch = '👏';

с комментарием: "unclosed character literal... illegal character: '\udc4f'".