英文:
Java SortMap Comparator to have digit keys ordered after letter keys
问题
public static void main(String[] args) {
SortedMap<Character, String> sortedMap = new TreeMap<>(new Comparator<Character>() {
@Override
public int compare(Character o1, Character o2) {
if (Character.isDigit(o1) && Character.isLetter(o2)){
return o2.compareTo(o1);
}
else if(Character.isLetter(o1) && Character.isDigit(o2)){
return o1.compareTo(o2);
}
else{
return o1.compareTo(o2);
}
}
});
sortedMap.put('5', "five");
sortedMap.put('8', "nine");
sortedMap.put('A', "ALPHA");
sortedMap.put('G', "GOLF");
sortedMap.put('F', "FOXTROT");
System.out.println(sortedMap.values());
}
英文:
I need a SortedMap where the Charachter keys are sorted this way: ('A'..'Z'..'0'..'9'), so character first, then digits, all in ascending order.
This is what I have tried so far, however, the output shows it fails in returning the sorting I want, because the values of the digit keys are still before the values of letter keys.
What am I doing wrong? Is there an even better way to do this?
Thanks in advance!
public static void main(String[] args) {
SortedMap<Character, String> sortedMap = new TreeMap<>(new Comparator<Character>() {
@Override
public int compare(Character o1, Character o2) {
if (Character.isDigit(o1) && Character.isLetter(o2)){
return o2.compareTo(o1);
}
else if(Character.isLetter(o1) && Character.isDigit(o2)){
return o1.compareTo(o2);
}
else{
return o1.compareTo(o2);
}
}
});
sortedMap.put('5', "five");
sortedMap.put('8', "nine");
sortedMap.put('A', "ALPHA");
sortedMap.put('G', "GOLF");
sortedMap.put('F', "FOXTROT");
System.out.println(sortedMap.values());
}
答案1
得分: 2
你需要在 o1 是数字而 o2 是字母的情况下返回结果 "o1 > o2",因此在这种情况下返回 1。类似地,如果 o1 是字母而 o2 是数字,你需要返回结果 "o1 < o2",即返回 -1。
public int compare(Character o1, Character o2) {
if (Character.isDigit(o1) && Character.isLetter(o2)){
return 1;
}
else if(Character.isLetter(o1) && Character.isDigit(o2)){
return -1;
}
else{
return o1.compareTo(o2);
}
}
英文:
You need to return the result "o1 > o2" if o1 is a digit and o2 is a letter, so return 1 in this case. Similarly, if o1 is a letter and o2 is a digit, you need to return the result "o1 < o2", i.e. return -1.
public int compare(Character o1, Character o2) {
if (Character.isDigit(o1) && Character.isLetter(o2)){
return 1;
}
else if(Character.isLetter(o1) && Character.isDigit(o2)){
return -1;
}
else{
return o1.compareTo(o2);
}
}
答案2
得分: 2
如果 o1
是一个字母而 o2
是一个数字,您应该始终返回 -1,因为您始终希望字母排在前面。而如果情况相反,您应该始终返回 1。
唯一的情况是在最后的 else
中应返回 o1.compareTo(o2)
,这意味着 o1
和 o2
都是字母或数字,此时比较器应该简单地遵循自然顺序。
英文:
You should always return -1 if o1
is a letter and o2
is a digit, because you always want the letter to go first. And you should always return 1 if it's the opposite.
The only case where it should return o1.compareTo(o2)
is in the final else
, which means o1
and o2
are both either letters or numbers, and in that case, the comparator should simply follow natural order.
答案3
得分: 1
假设您使用的是 Java 8+,请将您的 Map 声明为:
SortedMap<Character, String> sortedMap =
new TreeMap<>(Comparator.comparingInt(c -> (c + 197) % 255));
可选地,您可以将 "magic numbers" 197 和 255 提取为常量,或将 comparingInt(..)
的参数提取为常量。
解释:
字符 0 到 9 对应 ASCII 码 48 到 57
所有字母的 ASCII 码属于范围 65 到 122
上述代码将代码稍微偏移,将数字范围移动到 245 到 254,字母范围移动到 7 到 64
由于比较器比较了偏移后的代码,所以它会将字母排在数字之前
英文:
Asusuming you're using Java 8+, declare your Map as:
SortedMap<Character, String> sortedMap =
new TreeMap<>(Comparator.comparingInt(c -> (c + 197) % 255));
Optionally, you can extract "magic numbers" 197 and 255 into constants, or extract argument of comparingInt(..)
into a constant.
Explanation:
chars 0..9 correspond to ASCII codes 48..57
ASCII codes for all the letters belong to range 65..122
Code above shifts codes a bit, moving numbers range to 245..254 and letters range to 7..64
Since Comparator compares shifted codes, it places letters before digits
答案4
得分: 0
public int compare(Character o1, Character o2) {
if (Character.isDigit(o1) && Character.isLetter(o2)) {
// o1 < o2 regardless of what values o1 and o2 are
// So return any negative integer
return -100;
}
else if (Character.isLetter(o1) && Character.isDigit(o2)) {
// o1 > o2 regardless of what values o1 and o2 are
// So return any positive integer
return 100;
}
// Both must be letters or both must be integers
// fall back to normal comparison, as you have already done
return o1.compareTo(o2);
}
英文:
When you want all letters to come before all digits, and you get one digit and one letter, you should not be comparing them at all:
public int compare(Character o1, Character o2) {
if (Character.isDigit(o1) && Character.isLetter(o2)) {
// o1 < o2 regardless of what values o1 and o2 are
// So return any negative integer
return -100;
}
else if (Character.isLetter(o1) && Character.isDigit(o2)) {
// o1 > o2 regardless of what values o1 and o2 are
// So return any positive integer
return 100;
}
// Both must be letters or both must be integers
// fall back to normal comparison, as you have already done
return o1.compareTo(o2);
}
答案5
得分: 0
我更喜欢在 Map 的声明外部使用 ternary (?:)
结构来构建 Comparator
。我还添加了一些额外的值,与您的值交替,以增加变化性。
Comparator<Character> comp = (a, b) -> Character.isLetter(a)
&& Character.isDigit(b) ? -1 :
Character.isLetter(b) && Character.isDigit(a) ? 1 :
a.compareTo(b);
SortedMap<Character, String> sortedMap = new TreeMap<>(comp);
sortedMap.put('Q', "Quebec");
sortedMap.put('B', "Beta");
sortedMap.put('5', "five");
sortedMap.put('9', "nine");
sortedMap.put('A', "ALPHA");
sortedMap.put('3', "three");
sortedMap.put('G', "GOLF");
sortedMap.put('F', "FOXTROT");
sortedMap.entrySet().forEach(System.out::println);
打印输出结果为:
A=ALPHA
B=BETA
F=FOXTROT
G=GOLF
Q=QUEBEC
3=three
5=five
9=nine
英文:
I prefer using a ternary (?:)
construction outside the Map declaration to build the Comparator
. I also added some extra values interspersed with yours to add variability.
Comparator<Character> comp = (a, b) -> Character.isLetter(a)
&& Character.isDigit(b) ? -1 :
Character.isLetter(b) && Character.isDigit(a) ? 1 :
a.compareTo(b);
SortedMap<Character, String> sortedMap = new TreeMap<>(comp);
sortedMap.put('Q', "Quebec");
sortedMap.put('B', "Beta");
sortedMap.put('5', "five");
sortedMap.put('9', "nine");
sortedMap.put('A', "ALPHA");
sortedMap.put('3', "three");
sortedMap.put('G', "GOLF");
sortedMap.put('F', "FOXTROT");
sortedMap.entrySet().forEach(System.out::println);
Prints
A=ALPHA
B=BETA
F=FOXTROT
G=GOLF
Q=QUEBEC
3=three
5=five
9=nine
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论