此用例的Java集合

此用例的Java集合,java,data-structures,collections,set,hashcode,Java,Data Structures,Collections,Set,Hashcode,假设我们有一堆汽车物体 每辆车都有一些不同的属性,例如制造商、型号、年份等(这些属性可用于创建不同的哈希代码) 每辆车都有一个PurchaseOffer对象列表(PurchaseOffer对象包含定价\零售商信息) 我们收到来自多个不同来源的汽车列表,每辆汽车都有一个单独的购买报价。 问题是,这些列表可能重叠-一辆车可以出现在多个列表中 我们希望将列表汇总成一个汽车集合,其中每辆汽车都包含所有遇到的购买报价 我的问题是选择要在此聚合过程中使用的集合: 使用java.util.HashSet来存放

假设我们有一堆汽车物体

每辆车都有一些不同的属性,例如制造商、型号、年份等(这些属性可用于创建不同的哈希代码)

每辆车都有一个PurchaseOffer对象列表(PurchaseOffer对象包含定价\零售商信息)

我们收到来自多个不同来源的汽车列表,每辆汽车都有一个单独的购买报价。 问题是,这些列表可能重叠-一辆车可以出现在多个列表中

我们希望将列表汇总成一个汽车集合,其中每辆汽车都包含所有遇到的购买报价

我的问题是选择要在此聚合过程中使用的集合:

使用java.util.HashSet来存放我们的汽车感觉很自然,这样,当查看不同的汽车列表时,我们可以在摊销O(1)中检查集合中是否已经存在汽车, 但是,您无法从集合中检索元素(在我们的例子中,当我们遇到集合中已经存在的汽车时,我们希望根据其识别哈希代码从集合中检索该汽车,并向其添加PurchaseOffers)

我可以使用一个HashMap,其中每个汽车的hashCode映射到实际的汽车对象,但它可能不是教科书解决方案,因为它不安全-我必须确保自己的每个hashCode映射到一辆汽车与该hashCode-可能存在不一致性。 当然,我们可以创建一个指定的数据结构来保证这种一致性——难道还不应该存在吗

有人能提出我想要的数据结构吗,或者指出一个设计错误吗?
谢谢。

由于这是一种多对多关系,您需要一个双向多地图。Car是第一个的键,PurchaseOrder列表作为值。PurchaseOrder是第二个订单的关键,其值为汽车列表

底层实现是两个哈希映射


在上面放一个API,以获得所需的行为。或者看看能不能帮你。它是一个BiMap和两个multimap的组合。

基本数据结构应该是一个
HashMap
。这允许存储和接收一辆选定汽车的所有报价


现在,您可能需要为
Car.equals()
找到一个合适的实现,以确保来自不同来源的“Car”实际上是相同的。将
equals()
基于真实世界汽车(VIN)的唯一标识符怎么样?

创建扩展哈希的tout自定义类
Set,
覆盖方法包含(对象o)
检查操作系统哈希代码是否相同,并根据返回结果,将对象添加到集合中,并且仅当它不包含该对象时才添加该对象。定义新的自定义聚合类如何?定义hashcode,使汽车的id充当钥匙,并相应地覆盖equals()。定义接受原始汽车的自定义方法,并在列表上执行联合操作。最后,将自定义对象存储在哈希集中,以实现恒定时间查找

用纯粹的术语来说,聚合是一种超出单个对象范围的行为。访问者模式试图解决类似的问题


或者,如果您有一个sql数据存储,使用GROUPBY进行简单的选择就可以了

我认为你真的需要(至少)一个
HashMap
。。。正如@Andreas\u D建议的那样

您对每辆
汽车
已经有一张
列表
的反对意见与此无关。
HashMap
中的列表是聚合列表,包含所有
PurchaseOffer
对象,这些对象来自代表同一物理汽车的所有
Car
对象

创建新列表的目的是避免更改原始
Car
对象上的原始列表。(如果这不是问题,那么您可以从表示物理汽车的集合中选择一个
Car
实例,并将其他对象中的
PurchaseOffer
对象合并到该列表中。)

我不完全清楚@duffymo为什么建议在两个对象之间建立一个双向地图,但我认为这是因为不同来源的不同
Car
对象可能具有相同物理车的互补(或矛盾)信息。通过保留所有实例,可以避免丢弃信息。(同样,如果您愿意放弃变异和/或放弃信息,您可以尝试将有关每辆车的信息合并到单个
对象中


如果您真的不关心保存信息,并且准备随意地合并内容,那么以下方法可能会起作用:

  HashMap<Car, Car> map = new HashMap<Car, Car>(...);
  for (Car car : carsToBeAggregated) {
      Car master = nap.get(car);
      if (master == null) {
          map.put(car, car);
      } else {
          master.offers.addAll(car.offers);
          // optionally, merge other Car information from car to master
      }
  }
HashMap-map=新的HashMap(…);
用于(汽车:汽车聚集){
carmaster=nap.get(Car);
if(master==null){
放置(汽车,汽车);
}否则{
master.offers.addAll(car.offers);
//(可选)将其他车辆信息从车辆合并到主车辆
}
}


您不应该试图使用
Car.hashCode()
作为任何东西的钥匙。Hashcode值不是唯一标识符:两辆不同的车很可能会以相同的Hashcode值结束。如果你试图将它们当作唯一标识符来使用,你会遇到麻烦…

为什么不为此使用对象数据库?你可以存储你想要的任何对象图如果需要,您将获得一个搜索API,可以使用该API执行任何您想要的关系/检索机制。简单的集合可以工作,但听起来您需要一个比集合提供的关系更复杂的关系。查看db4o(http://db4o.com)-这类功能非常强大。

我更喜欢使用
HashMap
,如前所述(Andreas,Stephen),主要是在汽车对象不包含购买优惠列表的情况下。
否则,我会考虑使用<代码> HashMap < /代码>,或者更好的IMO,一个<代码> HashMap <代码>,如果有一个唯一的ID
    //alt. 1
    List<Offer> offers;
    List<Car> cars;
    Map<Car, List<Offer>> mapCarToOffers;
    Map<Offer, List<Car>> mapOfferToCars;
    public void List<Offer> getOffersForCar(Car aCar);
    public void List<Car> getCarsForOffer(Offer anOffer);
    //alt. 2
    List<Offer> offers;
    List<Car> cars;
    Map<Integer, List<Offer>> mapCarIdToOffers;
    Map<Integer, List<Car>> mapOfferIdToCars;
    public void List<Offer> getOffersForCarId(int aCarId);
    public void List<Car> getCarsForOfferId(int anOfferId);