0

我需要一个ArrayList<Coin>选择独特的元素并添加到另一个ArrayList<LineItem>。LineItem 包含 Coin 和第一个列表中匹配此硬币的数量。

我的代码有效但不正确,我不知道如何规避这个限制?

这是检查输出:

// it's list of coin's element
LineItem [quantity=1, theCoin=Coin[value=0.5,name=half dollar]]  
LineItem [quantity=1, theCoin=Coin[value=0.25,name=quantity dollar]] 
LineItem [quantity=1, theCoin=Coin[value=0.25,name=quantity dollar]]
LineItem [quantity=1, theCoin=Coin[value=0.5,name=half dollar]]
LineItem [quantity=1, theCoin=Coin[value=0.5,name=half dollar]]

// list of LineItem's element
[  
    LineItem [quantity=2, theCoin=Coin[value=0.5,name=half dollar]],   
    LineItem [quantity=2, theCoin=Coin[value=0.25,name=quantity dollar]],   
    LineItem [quantity=1, theCoin=Coin[value=0.5,name=half dollar]]  
]

元素列表LineItem应仅包含具有唯一性的元素name。如果名称在列表中,它应该只更新这个元素的数量。(我们只有 Coin half dollar 和数量 dollar 这两个元素。LineItem 列表必须只有这两个硬币名称,并且将数量匹配到 Coin 列表中)

代码:

private static ArrayList<LineItem> createItems(ArrayList<Coin> coins) {
    ArrayList<LineItem> itemsList = new ArrayList<LineItem>();

    for (Coin aCoin : coins) {
        LineItem anItem = new LineItem(aCoin, 1);
        System.out.println(anItem.toString()); // print every Coin element
        if (!itemsList.contains(anItem)) {
            itemsList.add(anItem);
        } else {
            int i = 0;
            boolean done = false;
            while (!done & i <= itemsList.size()) {
                Coin currentCoin = itemsList.get(i).getCoin();
                int currentQuantity = itemsList.get(i).getQuantity();
                if (currentCoin.equals(aCoin)) {
                    itemsList.get(i).setQuantity(currentQuantity + 1);
                    done = true;
                } else {
                    i++;
                }
            }
        }
    }
    System.out.println("\n" + itemsList.toString()); // print final LineItem's list
    return itemsList;
}

它将最后一个元素添加到此列表中,itemsList因为此列表不包含数量 == 1 的元素。但是此列表具有相同的Coin值。

如何解决这个麻烦?

4

4 回答 4

1

我认为问题出在equals——LineItem不仅要检查,Coin还要检查数量

所以当你调用List.contains它时,false如果你处理了两个相同的硬币,它就会返回。

您的代码的固定版本可能如下所示

for (Coin aCoin : coins) {
    boolean done = false;
    for (Iterator<LineItem> it = itemList.iterator();it.hasNext() && !done) {
        LineItem currentItem = it.next()
        Coin currentCoin = currentItem.getCoin();
        int currentQuantity = currentItem.getQuantity();
        if (currentCoin.equals(aCoin)) {
            currentItem.setQuantity(currentQuantity + 1);
            done = true;
        }
    }
    if(!done) {
        LineItem anItem = new LineItem(aCoin, 1);
        itemsList.add(anItem);
    }
}

但我更喜欢在这种情况下使用地图

添加地图代码

Map<Coin, LineItem> map = new HashMap<Coin, LineItem>();
for (Coin aCoin : coins) {
    LineItem anItem = map.get(aCoin);
    if(anItem == null) {
        map.put(aCoin, new LineItem(aCoin, 1));
    } else {
        anItem.setQuantity(anItem.getQuantity()+1);
    }
}
itemsList.addAll(map.values());

但是,如果您不使用 iverride,这将不起作用Coin#hashCode

于 2013-09-04T20:39:38.320 回答
0

我会建议另一种方法来实现这一目标:

  1. 覆盖 Coin 类中的 equals 方法,使其根据硬币值返回真/假。

  2. 遍历数组,将每个特定值的硬币添加到地图中,其中键为硬币面额,值为数量(like [0.25, 1]; [0.5, 2]

  3. 继续总结您的数量并替换此地图中特定面额的价值;这样在最后的地图看起来像:

0.25, 3 - 3 数量 0.25 面额硬币

0.5, 4 - 4 数量 0.5 面额硬币

4 最后遍历地图并创建要添加到 ArrayList 的 LineItem 对象。

于 2013-09-04T20:31:44.053 回答
0

尝试覆盖equals ()类 LineItem 中的

@Override
public boolean equals (Object obj) {
   return this.getCoin.equals (((LineItem)obj).getCoin);
}

这应该允许contains ()您列表中的方法检查硬币是否已经在列表中,而不管相关数量如何。

于 2013-09-04T20:39:27.173 回答
0

如果我理解你想要达到的目标,那就是......

您有一个第一个列表,其中包含:-

LineItem [quantity=1, theCoin=Coin[value=0.5,name=half dollar]]  
LineItem [quantity=1, theCoin=Coin[value=0.25,name=quantity dollar]] 
LineItem [quantity=1, theCoin=Coin[value=0.25,name=quantity dollar]]
LineItem [quantity=1, theCoin=Coin[value=0.5,name=half dollar]]
LineItem [quantity=1, theCoin=Coin[value=0.5,name=half dollar]]

但看起来你希望结果是: -

[LineItem [quantity=3, theCoin=Coin[value=0.5,name=half dollar]], LineItem [quantity=2, theCoin=Coin[value=0.25,name=quantity dollar]]

如果我是你来解决问题,我会在 Coin 上实现 equals 方法,它会比较值和名称。尽管在您的情况下,该值看起来就足够了。

例如

public boolean equals(Coin coinToCompare) {
    return value.equals(coinToCompare.getValue()) && name.equals(coinToCompare.getName());
}

如果您只是简单地执行 equals() 而不覆盖 equals() 方法,那么它只会进行参考比较,而不是按照您想要的方式进行比较。

另外,我认为您最好使用 HashMap 将键作为硬币的值,而不是使用允许重复的列表。

于 2013-09-04T20:45:29.900 回答