Java 中文字元按Unicode排序
遇到了一個對包含中文的字串進行排序的問題。要求按unicode編碼對字串進行排序。
測試字串陣列如下:
String[] arr = { "1-測試", "1-編輯", "1-營銷", "1結束", "2-測試", "1-qt" };
按unicode排序的期望結果應該是這樣的:
1-編輯, 1-測試, 1-營銷, 1-qt, 1結束, 2-測試
先按java.lang.String類提供的預設比較方案進行實現,大致如下:
import java.util.Arrays; import java.util.Comparator; public class MyJob { public static void main(String[] args) { String[] arr = { "1-測試", "1-編輯", "1-營銷", "1結束", "2-測試", "1-qt" }; Comparator<String> c = String::compareTo; Arrays.sort(arr, c); System.out.println(Arrays.toString(arr)); } }
結果如下:
[1-qt, 1-測試, 1-編輯, 1-營銷, 1結束, 2-測試]
可以看到中文字元不能按照拼音進行排序。這時最直接的思路就是將中文字元轉為拼音後再進行排序。但是要注意下,在這裡面有個字串不包含中文字元,這就容易導致順序混亂。
如下面這幾個字串按拼音進行排序順序如下:
1-編輯,1-測試,1-qt,1-營銷
可以看到字串“1-qt”的位置出錯了。 但是按拼音來說它的位置又是對的。這不能不說是一個讓人有些頭疼的地方。
不過不用擔心,java提供了java.text.Collator類來支援規範化的字串比較。
使用Collator來改造之前的程式碼:
import java.text.Collator; import java.util.Arrays; import java.util.Comparator; import java.util.Locale; public class MyJob { public static void main(String[] args) { String[] arr = { "1-測試", "1-編輯", "1-營銷", "1結束", "2-測試", "1-qt" }; Comparator<String> c = (o1, o2) -> Collator.getInstance(Locale.CHINESE).compare(o1, o2); Arrays.sort(arr, c); System.out.println(Arrays.toString(arr)); } }
改造後的程式執行排序的結果如下:
[1-qt, 1-編輯, 1-測試, 1結束, 1-營銷, 2-測試]
結果看著好像還OK。但是停停、注意下、字串“1結束”的位置好像比較奇妙,理想情況下它應該在“1-營銷”的後面。
這裡出問題的原因我沒有弄清楚。猜測著應該是java在Chinese語法中將中劃線處理為空字元了。不過最根本的問題還是java對Unicode Collation Algorithm(UCA,Unicode整理演算法)的支援並不好。
此時可以考慮使用IBM ICU提供的Collator來替換jdk預設的Collator。程式碼如下:
import com.ibm.icu.text.Collator; import java.util.Arrays; import java.util.Comparator; import java.util.Locale; public class MyJob { public static void main(String[] args) { String[] arr = { "1-測試", "1-編輯", "1-營銷", "1結束", "2-測試", "1-qt" }; Comparator<String> c = (o1, o2) -> Collator.getInstance(Locale.CHINESE).compare(o1, o2); Arrays.sort(arr, c); System.out.println(Arrays.toString(arr)); } }
相關的依賴為:
<dependency> <groupId>com.ibm.icu</groupId> <artifactId>icu4j-localespi</artifactId> <version>60.2</version> </dependency>
執行結果為:
[1-編輯, 1-測試, 1-營銷, 1-qt, 1結束, 2-測試]
可以看到是和預期一致的。
參考文件
- ofollow,noindex" target="_blank">Java Unicode strings sorting
- ICU User Guide – JNI
##########