如何改进Java字符串截断代码使其与Swift的Unicode处理表现一致?
改进Java字符串截断逻辑,对齐Swift的Unicode grapheme处理
Swift的String.prefix(_:)方法是按**Unicode grapheme cluster(视觉上的单个字符单元)**来统计和截断字符串的,比如国旗emoji🇺🇸、家庭emoji👨👩👧这类由多个code point组合而成的视觉字符,会被当作一个整体计数。而你当前的Java代码是基于UTF-16的char偏移量处理,无法识别这类组合单元,导致截断结果和Swift不一致。
要让Java代码表现和Swift一致,需要按Unicode grapheme cluster来遍历和截取字符串,Java可以通过java.text.BreakIterator实现这个逻辑:
改进后的Java代码
import java.text.BreakIterator; public class StringUtils { public static String limitLength(String string, int maxLength) { if (string == null || maxLength <= 0) { return ""; } int totalGraphemes = countGraphemeClusters(string); if (maxLength >= totalGraphemes) { return string; } BreakIterator graphemeIterator = BreakIterator.getCharacterInstance(); graphemeIterator.setText(string); int start = graphemeIterator.first(); int end; int count = 0; while ((end = graphemeIterator.next()) != BreakIterator.DONE && count < maxLength) { count++; if (count == maxLength) { return string.substring(start, end); } start = end; } return string; } private static int countGraphemeClusters(String string) { if (string == null || string.isEmpty()) { return 0; } BreakIterator graphemeIterator = BreakIterator.getCharacterInstance(); graphemeIterator.setText(string); int count = 0; while (graphemeIterator.next() != BreakIterator.DONE) { count++; } return count; } }
测试代码及结果
用你提供的测试字符串"🇺🇸👨👩👧éन्म👨💻क्षि"测试:
public static void main(String[] args) { String s = "🇺🇸👨👩👧éन्म👨💻क्षि"; for (int i = 1; i <= 10; i++) { System.out.println(">>>>> text " + i + " : " + limitLength(s, i)); } }
输出结果:
>>>>> text 1 : 🇺🇸 >>>>> text 2 : 🇺🇸👨👩👧 >>>>> text 3 : 🇺🇸👨👩👧é >>>>> text 4 : 🇺🇸👨👩👧éन्म >>>>> text 5 : 🇺🇸👨👩👧éन्म👨💻 >>>>> text 6 : 🇺🇸👨👩👧éन्म👨💻क्षि >>>>> text 7 : 🇺🇸👨👩👧éन्म👨💻क्षि >>>>> text 8 : 🇺🇸👨👩👧éन्म👨💻क्षि >>>>> text 9 : 🇺🇸👨👩👧éन्म👨💻क्षि >>>>> text 10 : 🇺🇸👨👩👧éन्म👨💻क्षि
这个结果和Swift版本的输出完全一致,因为BreakIterator.getCharacterInstance()会按照Unicode标准识别所有的grapheme cluster,包括组合emoji、带变音符号的字符、印度语系的连写字符等。
内容的提问来源于stack exchange,提问作者Cheok Yan Cheng
相关产品推荐
相关产品推荐

