gpt4 book ai didi

java - 收据是 Map 还是 Set

转载 作者:行者123 更新时间:2023-12-01 09:33:15 24 4
gpt4 key购买 nike

在我的应用程序中,我定义了自定义 Price 类型,如下所示

public final class Price {
private BigDecimal cash;
private Currency currency;
...
}

使用默认的 Object#equalsObject#hashCode 方法,因为它不是必需的(我从不检查 Price 对象逻辑相等性)。

此外,还有代表订单中商品总价的订单收据。如果订单中有 3 件商品,价格分别为 2 美元3 美元2 英镑,则收据应包含实体 5 美元2 英镑

现在,我将收据表示为带有 java.util.Currency 键的 map

Map<Currency, BigDecimal> receipt;

我的问题是,将其更改为是否是一个好的设计

Set<Price> receipt;

并重用我的自定义Price类型,并重写Object#equalsObject#hashCode方法作为

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

Price price = (Price) o;

return currency.equals(price.currency);
}

@Override
public int hashCode() {
return currency.hashCode();
}

这样

Price usd_2 = new Price(new BigDecimal(2), Currency.getInstance("USD"));
Price usd_3 = new Price(new BigDecimal(3), Currency.getInstance("USD"));
usd_2.equals(usd_3); // true

以这种方式覆盖相等方法是一个糟糕的选择吗?它在未来可能会导致什么陷阱?

最佳答案

您可以进行一些设计改进,我确信这些改进会出现在评论中,但我将忽略这些并专注于您的具体问题。

因此,在评论中,您说“收据”是:

It's a receipt for goods to be paid for. If Customer purchases 2 Items with prices 2 USD and 3 USD, then receipt contains 5 USD.

It represents total cost of the items, it does not track individual items.

Goods that refer to the same Receipt could be of different Currency, that's why I use Map. F.e, receipt may contain 5 USD and 4 GBP.

至于你关于将其从 Map 更改的问题到 Set :留下Map 。这是有道理的。您的收据是各种货币总计的集合,每种货币一个。您可以将其更改为 Set<Price>但是,正如您所发现的,您必须使用 equals 的奇怪的、违反直觉的实现。和hashCode ,以及 Set无论如何,并不能真正代表您正在做的事情:您的收据不是一组任意价格,而是货币到该货币总计的映射。

如果你真的想全力以赴,你可以做一个 Receipt类,例如:

public class Receipt {
private Map<Currency,Price> totals;
...
}

然后添加各种 getter 和 setter 来隐藏您正在使用 Map 的事实内部(例如 List<Currency> getCurrencies ()Price getTotal (Currency c) ,以及类似的东西)。但是,除了学习经验之外,您实际上并没有从简单的示例中获得太多收获。

至于你的equalshashCodePrice :

Will it be a bad choice to override equality methods in this way and what possible pitfalls it may cause in the future?

当然,这将是一个糟糕的选择。两个对象不应该相等,除非它们相等,并且仅比较价格的货币单位是没有意义的,因为 3 美元和 400 美元不相等。实现equalshashCode根据您的实际业务规则:

  • 对于equals两个价格不相等,除非它们的金额和货币单位相等。所以比较两者。
  • 对于hashCode它有点宽松,唯一真正的约束是 if equals()返回true对于两个对象,则它们的 hashCode()应该是一样的。但如果两个不相等的对象产生相同的哈希码也没关系。通常你会选择hashCode()这提供了哈希码的良好分布,因此对于您的情况,我要么返回例如cash.hashCode() ,或 cash 的某种组合和currency哈希码。

因此,使用 Set 并不是一个好主意。 -- 这样做意味着您必须拥有 equals()实现与现实并不相符。

希望有帮助。

关于java - 收据是 Map<Currency, BigDecimal> 还是 Set<Price>?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39222200/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com