Жодна із запропонованих відповідей не працює для сурогатних пар, які використовуються для кодування символів поза базовою багатолігальною площиною Unicode .
Ось приклад з використанням трьох різних прийомів для перебору символів рядка (у тому числі за допомогою потоку API Java 8). Зверніть увагу, що цей приклад включає символи Додаткової багатомовної площини Unicode (SMP). Для правильного відображення цього прикладу та результату потрібен правильний шрифт.
// String containing characters of the Unicode
// Supplementary Multilingual Plane (SMP)
// In that particular case, hieroglyphs.
String str = "The quick brown 𓃥 jumps over the lazy 𓊃𓍿𓅓𓃡";
Ітерація знаків
Перше рішення - це проста петля по всій char
рядку:
/* 1 */
System.out.println(
"\n\nUsing char iterator (do not work for surrogate pairs !)");
for (int pos = 0; pos < str.length(); ++pos) {
char c = str.charAt(pos);
System.out.printf("%s ", Character.toString(c));
// ^^^^^^^^^^^^^^^^^^^^^
// Convert to String as per OP request
}
Ітерація кодів
У другому рішенні також використовується явний цикл, але доступ до окремих точок коду за допомогою codePointAt та збільшення індексу циклу відповідно до charCount :
/* 2 */
System.out.println(
"\n\nUsing Java 1.5 codePointAt(works as expected)");
for (int pos = 0; pos < str.length();) {
int cp = str.codePointAt(pos);
char chars[] = Character.toChars(cp);
// ^^^^^^^^^^^^^^^^^^^^^
// Convert to a `char[]`
// as code points outside the Unicode BMP
// will map to more than one Java `char`
System.out.printf("%s ", new String(chars));
// ^^^^^^^^^^^^^^^^^
// Convert to String as per OP request
pos += Character.charCount(cp);
// ^^^^^^^^^^^^^^^^^^^^^^^
// Increment pos by 1 of more depending
// the number of Java `char` required to
// encode that particular codepoint.
}
Ітерація над кодовими точками за допомогою Stream API
Третє рішення в основному таке ж, як і друге, але використовуючи API Java 8 Stream :
/* 3 */
System.out.println(
"\n\nUsing Java 8 stream (works as expected)");
str.codePoints().forEach(
cp -> {
char chars[] = Character.toChars(cp);
// ^^^^^^^^^^^^^^^^^^^^^
// Convert to a `char[]`
// as code points outside the Unicode BMP
// will map to more than one Java `char`
System.out.printf("%s ", new String(chars));
// ^^^^^^^^^^^^^^^^^
// Convert to String as per OP request
});
Результати
Запустивши цю тестову програму, ви отримаєте:
Using char iterator (do not work for surrogate pairs !)
T h e q u i c k b r o w n ? ? j u m p s o v e r t h e l a z y ? ? ? ? ? ? ? ?
Using Java 1.5 codePointAt(works as expected)
T h e q u i c k b r o w n 𓃥 j u m p s o v e r t h e l a z y 𓊃 𓍿 𓅓 𓃡
Using Java 8 stream (works as expected)
T h e q u i c k b r o w n 𓃥 j u m p s o v e r t h e l a z y 𓊃 𓍿 𓅓 𓃡
Як ви бачите (якщо ви вмієте відображати ієрогліфи належним чином), перше рішення не обробляє належних символів поза межами BMP Unicode. З іншого боку, два інші рішення добре справляються із сурогатними парами.