java 哈希映射不更新特定键的整数值


package cdlKata;
import java.util.HashMap;
import java.util.Map;
class Item2 {
private String s;
public Item2(String s) { this.s = s; }
public String getS() { return s; }
}
class Basket2 {
private Map<Item2, Integer> items;
public Basket2() { items = new HashMap<>(); }
public Map<Item2, Integer> getItems() { return items; }
public void addItemToBasket(Item2 item) {
items.put(item, items.getOrDefault(item,0) + 1);
}
public void printBasket() {
items.entrySet().forEach(e->{ System.out.println(e.getKey().getS() + " " + e.getValue());});
}
}
public class Main2 {
public static void main(String[] args) {
Basket2 basket;
basket = new Basket2();
basket.addItemToBasket(new Item2("A"));
basket.addItemToBasket(new Item2("A"));
basket.printBasket();
}
}

结果是 :

一 1
一 1

篮子尺寸 = 2。我想要的是:

一 2

篮子尺寸为 1。

如果我将 Item2 转换为字符串,则没有问题。不要理解为什么它不起作用。


根据 HashMap 的工作逻辑,你必须覆盖密钥的 hashcode(( 和 equals(( 方法。 附言此外,我建议您在这种情况下使用映射的合并方法而不是放置。

map.merge(key, 1, Integer::sum)

您创建了两个不同的实例,如下所示

basket.addItemToBasket(new Item2("A"));
basket.addItemToBasket(new Item2("A"));

你期望它是平等的。事实并非如此。

您必须覆盖hashcodeequals

由于使用的是对象的映射,因此对输出进行整数处理:

一 1

一 1

是正确的,但您期望输出:A 2

为此,您需要创建字符串映射,整数,即item2.getS((和整数映射。

它不起作用的原因是因为您映射了对象和整数,并且您通过每次创建新对象将项目添加到购物篮中。

所以,解决方案将是这样的。

package cdlKata;
import java.util.HashMap;
import java.util.Map;
class Item2 {
private String s;
public Item2(String s) { this.s = s; }
public String getS() { return s; }
}
class Basket2 {
private Map<String, Integer> items;
public Basket2() { items = new HashMap<>(); }
public Map<String, Integer> getItems() { return items; }
public void addItemToBasket(Item2 item) {
items.put(item.getS(), items.getOrDefault(item.getS(),0) + 1);
}
public void printBasket() {
items.entrySet().forEach(e->{ System.out.println(e.getKey() + " " + e.getValue());});
}
}
public class Stack {
public static void main(String[] args) {
Basket2 basket;
basket = new Basket2();
basket.addItemToBasket(new Item2("A"));
basket.addItemToBasket(new Item2("A"));
basket.printBasket();
}
}

嗯... 你的类中缺少equals/hashCode。

有关更多信息,请参阅此答案:为什么我需要覆盖 Java 中的 equals 和 hashCode 方法?

对于您的类,只需定义以下方法:

class Item2 {
private String s;
public Item2(String s) { this.s = s; }
public String getS() { return s; }

@Override public boolean equals(Object o)
{
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
Item2 item2 = (Item2) o;
return s != null ? s.equals(item2.s) : item2.s == null;
}

@Override public int hashCode()
{
return s != null ? s.hashCode() : 0;
}
}

Is是使用哈希的常见错误。 你应该为项目类实现哈希代码和等于。

class Item2 {
private String s;
public Item2(String s) { this.s = s; }
public String getS() { return s; }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Item2)) return false;
Item2 item2 = (Item2) o;
return Objects.equals(getS(), item2.getS());
}
@Override
public int hashCode() {
return Objects.hash(getS());
}
}

如果没有它,HashMap 将认为两个对象(甚至相同的值(是不同的,因此,它将作为新对象放置。

最新更新