收据是Map <currency,bigdecimal =“”>还是Set <price>?

时间:2016-08-30 08:16:11

标签: java oop

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

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

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

此外,还有订单收据,表示订单中商品的总价。如果订单中有3个商品的价格为2 USD3 USD2 GBP,则收据应包含实体5 USD2 GBP

现在,我使用java.util.Currency

代表收据作为地图
Map<Currency, BigDecimal> receipt;

我的问题是,将它更改为

是否是一个好的设计
Set<Price> receipt;

并重复使用已覆盖的PriceObject#equals方法的自定义Object#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

以这种方式覆盖平等方法以及未来可能导致的陷阱是不是一个糟糕的选择?

1 个答案:

答案 0 :(得分:1)

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

所以,在评论中,你说一个&#34;收据&#34;是:

  

它是要支付货物的收据。如果客户购买2件物品,价格为2美元和3美元,则收据包含5美元。

     

它表示项目的总成本,它不跟踪单个项目。

     

引用同一收据的商品可能具有不同的货币,这就是我使用地图的原因。 F.e,收据可能包含5美元和4英镑。

关于将其从Map更改为Set的问题,请将其保留为Map。这是有道理的。您的收据是各种货币总计的集合,每种货币一个。您可以将其更改为Set<Price>但是,正如您所发现的那样,您必须使用equalshashCode的奇怪,违反直觉的实现,并且Set并不能真实地代表您正在做的事情:您的收据不是任意价格的集合,而是将货币映射到该货币的总计。< / p>

如果你真的想要在其上使用所有OO,你可以制作一个Receipt类,例如:

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

然后添加各种getter和setter,隐藏您在内部Map使用List<Currency> getCurrencies ()的事实(例如Price getTotal (Currency c)equals等等)。但是,除了学习经验之外,你在

至于hashCode中的Priceequals

  

以这种方式覆盖平等方法以及将来可能导致的陷阱是不是一个糟糕的选择?

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

  • 对于hashCode,除非它们的金额和货币单位相等,否则两个价格不相等。所以比较两者。
  • 对于equals()它稍微宽松一点,唯一真正的限制是如果true为两个对象返回hashCode(),那么它们的hashCode()应该是相同的。但是,如果两个不相等的对象产生相同的哈希码,那也没关系。通常你选择一个cash.hashCode()可以很好地分配哈希码,所以对于你的情况,我要么返回,例如cash,或currencySet哈希码的某种组合。

正因为如此,使用equals()并不是一个好主意 - 这样做意味着你必须拥有一个viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener(){ @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { conterchange.setText(""+(1+position)); } @Override public void onPageSelected(int position) { } @Override public void onPageScrollStateChanged(int state) { } }); 实施,而不是java.awt.Component真的和现实一致。

希望有所帮助。