【问题标题】:Is there a Char collator in Java?Java中是否有Char整理器?
【发布时间】:2016-12-09 16:19:53
【问题描述】:

我正在开发一个小应用程序,它可以计算文本中的字符出现并打印一个简单的报告。它基于 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 构造函数可以使用整理器,但不能用于 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与地图绑定?

【问题讨论】:

  • 您可以使用collator.compare(String.valueOf(c1), String.valueOf(c2));,其中c1c2 是字符。
  • 我不知道。考虑使用String.valueOf(char)
  • “计算字符外观的应用程序”Collator 有什么关系,Collator 用于“为自然语言文本构建搜索和排序例程”? Collat​​ioncounting 没有任何关系。这是关于排序
  • @Andreas 好吧,它也打印出来了。
  • 我添加了关于String.valueOf的更新。

标签: java char collation


【解决方案1】:

更新

如果您只希望Collator 在打印时对结果进行排序,则只需在计数后排序即可。性能要好得多。进一步查看代码。

如果您希望TreeMap 使用Collator,请获取Collator,然后将Comparator&lt;Character&gt; 提供给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

如您所见,结果是根据德国排序规则打印的,äab 之间。

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

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),有时您会收到一个重音字母(例如ü)。 这对我来说似乎是错误的。

【讨论】:

  • 正是我想要的,谢谢。顺便说一句,HashMap 比 TreeMap 慢。
  • 为什么警告被禁止?
  • 因为我接受了警告,不想再看到了。
  • 您的代码中有一个小错误,我已更正。
【解决方案2】:

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

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

那么排序就没有问题了。

顺便说一下,Character 有很多不错的 Unicode 信息:

String name = Character.getName(codePoint);

【讨论】:

  • 这与问题有什么关系?没错,对于完整的 Unicode 支持,地图应该由代码点键入,但这并不能回答有关使用 Collator 的实际问题。因此,这应该是评论,而不是答案。 --- 而且我不明白为什么使用代码点会让你说“那么排序没问题”。 TreeMap 仍将按 Unicode 值排序,而不是根据某些语言环境按字母顺序排列。从char 更改为代码点不会影响排序顺序,补充字符除外。
  • 首先,我不确定我需要一个字符串来做什么。我宁愿留在 Char 级别。其次,我希望能够按照给定的语言环境对 Char 键控地图进行排序。进入代码点是否有助于实现这一目标?
  • @tomas 如果您的文本可以包含来自 Unicode 中的补充平面的字符(主要是表情符号),那将是一个问题。如果您的文本有,它们在 Java 中存储为两个代理对 char 值,因此您将计算单个代理字符,而不是实际的 Unicode 字符,
  • @Andreas 好的。它们是 UTF-16 吗? UTF-32?据我所知,Java 是基于 UTF-8 的。我的程序适用于所有日文和中文字符吗?如何解决这个问题?
  • Java Stringchar 是 UTF-16。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多