Java中是否有Char collat​​or?

时间:2016-08-03 19:30:36

标签: java char collation

我正在开发一个小应用程序,它可以计算文本中的字符外观并打印一个简单的报告。它基于TreeMap。它应该适用于任何UTF-8(迄今为止)可编码语言。当我尝试通过调用Collator.getInstance()来使用标准整理器时,我得到异常java.lang.ClassCastException: java.lang.Character cannot be cast to java.lang.String

有没有Char collat​​or?

static Map<Character, Integer> map = new TreeMap<>(); 

TreeMap构造函数可以使用collat​​or,但不能用于Chars。

public static void main(String[] args) {
    InputStream in = System.in;

    try {
        if (in.available() == 0) System.exit(0);
    } catch (IOException e) {
        e.printStackTrace();
    }

    count(in);  
    printMap();
} 


static void count(InputStream in) {
    new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))   
        .lines()
        .forEach(x -> tallyCharArray(x.toCharArray()));
}

static void tallyCharArray (char[] chars) {
    for (int i=0; i<chars.length; i++) {
        map.merge(chars[i], 1, Integer::sum);
    }
}

static void printMap() {
    map.entrySet().stream()
    .forEach(x -> System.out.println(x.getKey() + "\t" + x.getValue()));
}

比较问题

static Map<Character, Integer> map = new TreeMap<>(
    Collator.getInstance().compare(String.valueOf(c1), String.valueOf(c2))
);

这很笨拙,但它还没有奏效。如何将c1c2与地图绑定?

2 个答案:

答案 0 :(得分:1)

<强>已更新

如果您只希望Collator在打印时对结果进行排序,请在计数后进行排序。表现要好得多。请进一步查看代码。

如果您希望TreeMap使用Collator,请获取Collator,然后将Comparator<Character>提供给TreeMap构造函数。由于您使用的是Java 8流,因此您可以使用lambda表达式执行此操作:

Collator collator = Collator.getInstance(Locale.GERMAN);
collator.setStrength(Collator.PRIMARY);
Map<Character, int[]> countMap = new TreeMap<>(
        (c1, c2) -> collator.compare(c1.toString(), c2.toString())
);

使用Collator,重音符号和大写/小写字符全部合并。请参阅本答案末尾的示例输出。

计算后排序的完整代码

String input = "Das Polaritätsprofil für das Wort \"Hund\" als Testeinheit " +
               "könnte zeigen , dass verschiedene Personen unterschiedliche " +
               "Einstellungen zu diesen Tieren haben .";

Map<Character, int[]> countMap = new HashMap<>();
for (Character ch : input.toCharArray()) {
    int[] counter = countMap.get(ch);
    if (counter == null)
        countMap.put(ch, new int[] { 1 });
    else
        counter[0]++;
}
@SuppressWarnings("unchecked")
Entry<Character, int[]>[] counts = countMap.entrySet().toArray(new Map.Entry[countMap.size()]);
Collator collator = Collator.getInstance(Locale.GERMAN);
Arrays.sort(counts, (e1, e2) -> collator.compare(e1.getKey().toString(), e2.getKey().toString()));
for (Entry<Character, int[]> entry : counts)
    System.out.printf("%c - %d%n", entry.getKey(), entry.getValue()[0]);

计算后的排序输出

, - 1
. - 1
" - 2
  - 20
a - 6
ä - 1
b - 1
c - 3
d - 6
D - 1
E - 1
e - 22
f - 2
g - 2
h - 5
H - 1
i - 11
k - 1
l - 6
n - 15
ö - 1
o - 4
P - 2
p - 1
r - 8
s - 12
t - 8
T - 2
u - 4
ü - 1
v - 1
W - 1
z - 2

如您所见,结果是根据德语整理打印的,äa之间的b

如果你想要统一大写和小写字符,你应该在结果中决定你想要哪个并转换成那个,否则它将是任意的。

PRIMARY

中使用Collator TreeMap的输出
  - 20
, - 1
. - 1
" - 2
a - 7
b - 1
c - 3
D - 7
e - 23
f - 2
g - 2
H - 6
i - 11
k - 1
l - 6
n - 15
o - 5
P - 3
r - 8
s - 12
t - 10
ü - 5
v - 1
W - 1
z - 2

正如您所看到的,有时您会得到一个小写字母(例如a),有时您会得到一个大写字母(例如D),有时您会得到一个带重音的字母(例如{{1} }})。 这对我来说似乎不对。

答案 1 :(得分:0)

char是UTF-16格式的2字节值。 Unicode符号,代码点,达到3字节范围,在java中表示为 int 。所以最好使用代码点。从它们创建一个String,如下所示:

int codePoint = ...
int[] codePoints = { codePoint };
String s = new String(codePoints, 0, codePoints.length);

然后整理是没问题的。

顺便说一句,Character有许多不错的Unicode信息:

String name = Character.getName(codePoint);
相关问题