Java 中是否有 Char 整理器?
Is there a Char collator in Java?
我正在开发一个小应用程序,它计算文本中字符的出现次数并打印一份简单的报告。它基于 TreeMap。它应该与任何 UTF-8(到目前为止)可编码语言一起使用。当我尝试通过调用 Collator.getInstance()
来使用标准整理器时,出现异常 java.lang.ClassCastException: java.lang.Character cannot be cast to java.lang.String
.
有没有Char整理器?
static Map<Character, Integer> map = new TreeMap<>();
TreeMap 构造函数可以采用整理器,但不能用于字符。
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))
);
这很笨拙,还行不通。 c1
和c2
如何绑定地图?
已更新
如果打印时只需要Collator
对结果进行排序,只需在计数后排序即可。性能要好得多。进一步查看代码。
如果你想让TreeMap
使用Collator
,得到Collator
,然后给TreeMap
构造函数一个Comparator<Character>
。由于您使用的是 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
,重音和 upper-/lower-case 字符全部合并。请参阅此答案末尾的示例输出。
计数后排序的完整代码
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
之间。
如果你想统一大小写字符,你应该在结果中决定你想要哪个并转换成那个,否则它是任意的。
在TreeMap
中使用PRIMARY
Collator
的输出
- 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
),有时您会得到一个重音字母(例如 [= =29=]). 这对我来说似乎是错误的。
A char
是 UTF-16 格式的 2 字节值。 Unicode 符号,代码点,达到 3 字节范围,在 java 中表示为 int。所以最好使用代码点。从它们中创建一个字符串,如下所示:
int codePoint = ...
int[] codePoints = { codePoint };
String s = new String(codePoints, 0, codePoints.length);
那么整理就没问题了
顺便说一句,Character 有很多不错的 Unicode 信息:
String name = Character.getName(codePoint);
我正在开发一个小应用程序,它计算文本中字符的出现次数并打印一份简单的报告。它基于 TreeMap。它应该与任何 UTF-8(到目前为止)可编码语言一起使用。当我尝试通过调用 Collator.getInstance()
来使用标准整理器时,出现异常 java.lang.ClassCastException: java.lang.Character cannot be cast to java.lang.String
.
有没有Char整理器?
static Map<Character, Integer> map = new TreeMap<>();
TreeMap 构造函数可以采用整理器,但不能用于字符。
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))
);
这很笨拙,还行不通。 c1
和c2
如何绑定地图?
已更新
如果打印时只需要Collator
对结果进行排序,只需在计数后排序即可。性能要好得多。进一步查看代码。
如果你想让TreeMap
使用Collator
,得到Collator
,然后给TreeMap
构造函数一个Comparator<Character>
。由于您使用的是 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
,重音和 upper-/lower-case 字符全部合并。请参阅此答案末尾的示例输出。
计数后排序的完整代码
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
之间。
如果你想统一大小写字符,你应该在结果中决定你想要哪个并转换成那个,否则它是任意的。
在TreeMap
PRIMARY
Collator
的输出
- 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
),有时您会得到一个重音字母(例如 [= =29=]). 这对我来说似乎是错误的。
A char
是 UTF-16 格式的 2 字节值。 Unicode 符号,代码点,达到 3 字节范围,在 java 中表示为 int。所以最好使用代码点。从它们中创建一个字符串,如下所示:
int codePoint = ...
int[] codePoints = { codePoint };
String s = new String(codePoints, 0, codePoints.length);
那么整理就没问题了
顺便说一句,Character 有很多不错的 Unicode 信息:
String name = Character.getName(codePoint);