java - 无法将 Char 和 Int HashMap 转换为字符串
问题描述
我一直在试图弄清楚如何将所有元素(键和值)转换为字符串。例如,结果应该类似于“a2b3c4”。
import java.util.*;
class Main{
public static String stringCompression(String s){
s = s.toLowerCase();
HashMap<Character,Integer> map = new HashMap<>();
for (int i = 0; i < s.length(); i++){
char c = s.charAt(i);
if (map.containsKey(c)){
map.put(c, map.get(c) + 1);
}
else{
map.put(c, 1);
}
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < map.size(); i++){
sb.append(map.get(i));
}
return sb.toString();
}
public static void main (String[] args){
System.out.println(stringCompression("aabccccaaa"));
System.out.println(stringCompression("abc"));
System.out.println(stringCompression("AabBcCdDdDDeE"));
}
}
解决方案
tl;博士
map.get( i )
是不正确的。您的键是Character
对象,而不是int i
循环中使用的对象。
调用Map#keySet
并循环这些关键对象,而不是递增int i
. 替换你for (int i = 0; i < map.size(); i++){
的for ( Character key : map.keySet() )
细节
顺便说一句,您使用“压缩”一词,但您所做的不是压缩。您正在计算每个字符的总重复次数,而不是分别计算重复字符的每个系列。
您用于填充地图的代码是正确的。我们可以通过println
查看地图的内容来看到这一点。对于输入"aabccccaaa"
,我们得到这张地图:map.toString(): {a=5, b=1, c=4}
.
问题在于您使用StringBuilder
. 你打电话map.get( i )
。这意味着您要求映射到 0、1、2 等键的值。但是您没有使用整数作为密钥。您正在使用Character
作为您的密钥类型。
相反,您应该在所有键的集合上循环。然后get
为每个键做一个。您的StringBuilder
代码应如下所示:
StringBuilder sb = new StringBuilder();
Set < Character > keys = map.keySet();
for ( Character key : keys )
{
Integer count = map.get( key );
sb.append( key ).append( count );
}
顺便说一句,您可以通过使用方法将您插入到地图中的单行调用中Map#merge
。所以这:
if (map.containsKey(c)){
map.put(c, map.get(c) + 1);
}
else{
map.put(c, 1);
}
…变成这样:
map.merge( c , 1 , Integer :: sum );
这Integer :: sum
是一个方法参考。方法引用是表示该方法而不是调用该方法的对象。该方法将在执行其工作merge
时调用该方法。sum
顺便说一句,您的行用一个新对象s = s.toLowerCase();
替换了传递的参数对象。我不推荐这个。你放弃了原文,却一无所获。您已经丢弃了调试和记录所需的有价值的信息。相反,定义一个新变量:. 并且为了防止参数变量的这种重新分配,将参数声明标记为.String
String
String
String input = s.toLowerCase();
final
完整的代码示例:
package work.basil.example;
import java.util.HashMap;
import java.util.Set;
public class RepeatCounter
{
public static void main ( String[] args )
{
System.out.println( countCharacterOccurrence( "aabccccaaa" ) );
System.out.println( countCharacterOccurrence( "abc" ) );
System.out.println( countCharacterOccurrence( "AabBcCdDdDDeE" ) );
}
public static String countCharacterOccurrence ( final String s )
{
String input = s.toLowerCase();
HashMap < Character, Integer > map = new HashMap <>();
for ( int i = 0 ; i < input.length() ; i++ )
{
char c = input.charAt( i );
map.merge( c , 1 , Integer :: sum );
}
// System.out.println( "map = " + map );
StringBuilder sb = new StringBuilder();
Set < Character > keys = map.keySet();
for ( Character key : keys )
{
Integer count = map.get( key );
sb.append( key ).append( count );
}
return sb.toString();
}
}
跑的时候。
a5b1c4
a1b1c1
a2b2c2d5e2
您可能希望使用其他Map
实现而不是HashMap
. 该类HashMap
不承诺其键的迭代顺序。
如果您希望键按排序顺序保存,请使用SortedMap
/NavigableMap
实现,例如TreeMap
.
如果您希望键保持其原始插入顺序,请使用LinkedHashMap
.
Map
这是我用 Java 捆绑的实现制作的图表。
顺便说一句,Java 中的char
/Character
类型已经过时,甚至无法表示Unicode中定义的 143,859 个字符的一半。
虽然您的代码可以处理“Hello World”的输入,但它会因输入“Hello world ️”而失败。
学习使用整数代码点编号。因此,您的 Map 将是Map < Integer , Integer >
第一个Integer
表示每个字符的代码点编号,第二个Integer
是其出现次数的地方。
有关更多信息,请阅读:每个软件开发人员绝对、肯定必须了解 Unicode 和字符集的绝对最低要求(没有借口!)。
推荐阅读
- mysql - MySQL 8.0 程序输出参数为空
- amazon-web-services - 将 AWS Lambda 响应保存到 S3 的更好方法
- laravel - 如何使用 Laravel 自定义消息验证器
- xamarin - 如何显示 UIDatePicker 以选择日期
- sharepoint - 某些用户看不到 SharePoint 工作流
- angular - Angular 没有显示来自 Laravel Validator 的所有错误
- javascript - 如何下载高质量的 Instagram 个人资料图片 (InstaDP)?
- python - ModuleNotFoundError:将 Django 应用程序部署到 AWS Elastic Beanstalk 时没有名为“setuptools_rust”的模块
- c++ - lldb: 不能从类型 'std::__1::shared_ptr
' 指向指针类型 'Pkt1*' - java - ImageView 返回到 Android 中 Drawable 文件设置的 Null