提问人:Akash 提问时间:11/2/2023 最后编辑:Mike 'Pomax' KamermansAkash 更新时间:11/2/2023 访问量:99
为什么在遍历哈希图时会打印重复的键?[已结束]
Why are duplicate keys printed when I'm looping through the hashmap? [closed]
问:
我的代码有什么问题?我正在尝试打印密钥,但是当我打印时,我得到了重复的密钥。我的印象是,当我们向哈希图添加重复键时,它会替换以前的键。
我正在尝试打印数组中的所有重复元素。
public static void repeatingElements(int a[], int n) {
HashMap<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < n; i++) {
if (map.containsKey(a[i])) {
map.put(a[i], map.get(a[i]) + 1);
} else {
map.put(a[i],1);
}
for (Map.Entry<Integer, Integer> entry: map.entrySet()) {
if (entry.getValue()>1) {
System.out.print(entry.getKey() + " ");
}
}
}
}
- 输入:
{12, 10, 9, 45, 2, 10, 10, 45}
- 预期输出:
10 45
- 我得到的输出:
10 10 10 45
答:
0赞
MWB
11/2/2023
#1
难道不是您的打印循环在错误的位置的问题吗?
public static void repeatingElements(int a[], int n){
HashMap<Integer, Integer> map = new HashMap<>();
for(int i=0;i<n;i++){
if(map.containsKey(a[i])){
map.put(a[i], map.get(a[i]) + 1);
}
else {
map.put(a[i],1);
}
}
for(Map.Entry<Integer, Integer> entry: map.entrySet()){
if(entry.getValue()>1){
System.out.print(entry.getKey() + " ");
}
}
}
1赞
vsfDawg
11/2/2023
#2
您得到的输出是在 for 循环的每次迭代中发出 Map 状态的结果。
考虑每次迭代时 Map 的状态:
12: [{12:1}] Output:
10: [{12:1}, {10:1}] Output:
9: [{12:1}, {10:1}, {9:1}] Output:
45: [{12:1}, {10:1}, {9:1}, {45:1}] Output:
2: [{12:1}, {10:1}, {9:1}, {45:1}, {2:1}] Output:
10: [{12:1}, {10:2}, {9:1}, {45:1}, {2:1}] Output: 10
10: [{12:1}, {10:3}, {9:1}, {45:1}, {2:1}] Output: 10
45: [{12:1}, {10:3}, {9:1}, {45:2}, {2:1}] Output: 10 45
因此,总输出最终为:10 10 10 45
解决方案是在循环之后移动该状态输出。
public static void repeatingElements(int a[], int n){
HashMap<Integer, Integer> map = new HashMap<>();
for(int i=0;i<n;i++){
if(map.containsKey(a[i])){
map.put(a[i], map.get(a[i]) + 1);
} else {
map.put(a[i],1);
}
}
for(Map.Entry<Integer, Integer> entry: map.entrySet()){
if(entry.getValue()>1){
System.out.print(entry.getKey() + " ");
}
}
}
0赞
WJS
11/2/2023
#3
- 对于首次遇到的所有值,请输入默认值 1。重复的键将替换当前值。
- 找到每个键时,其值将替换为当前值加 1。
- 因此,在第一个循环结束时,您的地图看起来像这样,因为发生次数和发生次数。
10
3
45
2
2=1
9=1
10=3
12=1
45=2
现在,如果你把最后一个循环移到第一个循环之外,你会得到以下内容。
10 45
这是修改后的代码。
public static void repeatingElements(int a[], int n) {
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < n; i++) {
if (map.containsKey(a[i])) {
map.put(a[i], map.get(a[i]) + 1);
} else {
map.put(a[i], 1);
}
}
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
if (entry.getValue() > 1) {
System.out.print(entry.getKey() + " ");
}
}
}
如果您只想检测哪些项目是重复项,而不关心它们出现多少次,则可以使用集。
- 如果该值在添加到集合时已经存在,则返回 false,因此将其添加到集合中。
seen
dups
- 由于不会保留重复项,因此继续添加现有值不会有任何区别。
sets
public static void repeatingElements(int vals[]) {
Set<Integer> seen = new HashSet<>();
Set<Integer> dups = new HashSet<>();
for(int val : vals) {
if (!seen.add(val)) {
dups.add(val);
}
}
System.out.println(dups);
}
指纹
[10, 45]
0赞
Reilas
11/2/2023
#4
"...我的印象是,当我们向哈希图添加重复键时,它会替换以前的键。..."
没错,它用相同的“哈希码”替换了密钥。
这是来自 OpenJDK 的源代码。
GitHub – java/util/HashMap.java – putVal。
“为什么在我遍历哈希图时打印重复的键?...
。我正在尝试打印数组中的所有重复元素。..."
在循环后打印值。
HashMap<Integer, Integer> map = new HashMap<>();
for(int i=0;i<n;i++){
if(map.containsKey(a[i])){
map.put(a[i], map.get(a[i]) + 1);
}
else {
map.put(a[i],1);
}
}
for(Map.Entry<Integer, Integer> entry: map.entrySet()){
if(entry.getValue()>1){
System.out.print(entry.getKey() + " ");
}
}
作为参考,您可以使用 Map#compute 方法。
for(int i=0;i<n;i++)
map.compute(a[i], (k, v) -> v == null ? 1 : ++v);
或者,Map#merge 和 Integer#sum 方法。
for(int i=0;i<n;i++)
map.merge(a[i], 1, Integer::sum);
另一种方法是使用 Collections#frequency 方法和 Set。
void repeatingElements(int a[]){
List<Integer> list = IntStream.of(a).boxed().toList();
new HashSet<>(list).forEach(
x -> {
if (Collections.frequency(list, x) > 1)
System.out.print(x + " ");
});
}
评论
0赞
WJS
11/2/2023
我假设您意识到,对于每次调用,它都会遍历集合中每个值的整个列表。Collections.frequency
上一个:未定义的局部变量或方法
下一个:键值存储属性
评论
System.out.println(map);