Java 比较相同的字符会得到不同的结果
我试图制作一个程序,统计用户输入短语中字母的所有实例。例如,短语“Hello”将输出Java 比较相同的字符会得到不同的结果,java,count,Java,Count,我试图制作一个程序,统计用户输入短语中字母的所有实例。例如,短语“Hello”将输出“h:1”、“e:1”、“l:2”、“o:1” 我已经学会了如何查找和计数所有字母,除了“a”。当我多次将“a”与其自身进行比较时,它每次都返回不同的值(因此短语“aaaa”将给出a:1、b:1、c:1、d:1) 以下是我使用的代码: int[]countLetter=newint[26]; 字符[]字母表={'a','b','c','d','e','f','g','h','i','j','k','l','m',
“h:1”、“e:1”、“l:2”、“o:1”
我已经学会了如何查找和计数所有字母,除了
“a”
。当我多次将“a”
与其自身进行比较时,它每次都返回不同的值(因此短语“aaaa”
将给出a:1、b:1、c:1、d:1
)
以下是我使用的代码:
int[]countLetter=newint[26];
字符[]字母表={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
短语=短语.toLowerCase();
字符串a=“a”;
对于(int i=0;i您永远不应该依赖compareTo
的确切返回值,除非它是0
。如果您想将字符a
、b
、c
等转换为数组的索引,最好的方法是找到它们之间的差异a
。这样a
就被转换为0
,b
至1
等:
for(int i=0;i
我建议使用另一种方法,使用a可能是解决此问题的更好方法,地图可以在每个条目中存储2个内容,因此在键中可以存储短语的字符和字符的实例数作为值,下面是一个带有注释的示例:
public static void main(String[] args) {
String phrase = "hello";
HashMap<Character, Integer> map = new HashMap<Character, Integer>(); // Define a map, key type character, value type integer
phrase = phrase.toLowerCase();
for (int i = 0; i<phrase.length(); i++ ) { // iterate phrase
char c = phrase.charAt(i); // get current character
if(map.containsKey(c)) // if key already exists in the map
map.put(c, map.get(c) + 1); // increment the current value by 1 for this character
else // if key doesn't exists in the map yet
map.put(c, 1); // add the character with a value of 1
}
for (Map.Entry<Character, Integer> entry : map.entrySet()) { // iterate map
System.out.println(entry.getKey() + ": " + entry.getValue()); // print key and value
}
}
输入:“aaaa”
输出:
e: 1
h: 1
l: 2
o: 1
a: 4
这是因为compareTo
比较整个字符串,因此如果该字符串连续包含相同的字符,结果将发生变化。在代码中,您将compareTo
与phrase.substring(i)
进行比较,以便发送整个字符串。
如果要使用compareTo
替换phrase.substring(i)
byphrase.charAt(i)+“
但实际上,您永远不应该将代码基于compareTo
的返回值。相反,使用字符本身,因为字符是一个数字。代码中的错误是因为compareTo返回结果的方式。正如Mureinik所说,“您永远不应该依赖compareTo的确切返回值”。我将尝试一下去解释哪里出了问题
如果两个字符串不同,则要么它们在某个索引处具有不同的字符,而该索引是两个字符串的有效索引,要么它们的长度不同,或者两者都不同。如果它们在一个或多个索引位置具有不同的字符,则k是此类索引的最小值。然后,compareTo方法返回
return str1.charAt(k) - str2.charAt(k);
如果索引位置不存在差异,则按字典顺序,较短的字符串优先于较长的字符串。在这种情况下,compareTo返回字符串长度的差异
return str1.length() - str2.length();
当短语字符串为“aaaaa”时,对于0-4之间的不同值,会发生这种情况
//when i = 0
a.compareTo(phrase.substring(i))
//"a".compareTo("aaaaa")
//length of "a" - length of "aaaaaa"
//which is -4
将它与-1相乘,就像你所做的那样,-4变为4,这是字母“e”的索引。你可以检查i的其他值,你就会明白这就是为什么d,c,b和一个计数器等于1
我希望我帮你找到了错误。
有关compareTo()的更多详细信息,请查看此链接
如果允许您使用lambda,您的程序将大大缩短:
创建地图:
Map<Character,Long> counts = phrase.chars().boxed().collect(
groupingBy( t -> (char)(int)t, counting() ) );
获取:e:1,h:1,l:2,o:1
您基本上使用的是String.compareTo
,但这种方式非常奇怪,这并不是您想要的。请考虑一下您试图用表达式a.compareTo(短语.子字符串(i))实现什么*-1
然后以更简单、更准确的方式编写。提示:您可能希望使用(名称略为隐晦)count
变量,而不是使用子字符串。。。
Map<Character,Long> counts = phrase.chars().boxed().collect(
groupingBy( t -> (char)(int)t, counting() ) );
StringJoiner joiner = new StringJoiner( ", " );
for( char c = 'a'; c <= 'z'; c++ )
if( counts.containsKey( c ) )
joiner.add( c + ": " + counts.get( c ) );
System.out.println( joiner );