我需要一个ArrayList<Coin>
选择唯一元素并添加到另一个ArrayList<LineItem>
。 LineItem包含硬币和第一个列表中匹配此硬币的数量。
我的代码有效,但不正确,我不知道如何规避这个限制?
这是检查输出:
// 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
元素。
如果name在列表中,它应该只更新该元素的数量。
(我们只有两个元素在硬币半美元和数量美元.LineItem列表必须只有这两个硬币名称并将数量匹配到硬币列表中)
代码:
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
值。
如何解决这个问题?
答案 0 :(得分:1)
我认为问题出现在equals
的{{1}}中 - 它不仅检查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);
}
}
但是如果你没有iverride 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());
答案 1 :(得分:0)
我建议采用另一种方法来实现这一目标:
覆盖Coin类中的equals方法,使其返回 基于硬币值的真/假。
遍历数组,在地图中添加特定值的每个硬币,其中键作为硬币面额,值为数量(like [0.25, 1]; [0.5, 2]
)
继续总结您的数量并替换此地图中特定面额的值;这样在结尾的地图上看起来像:
0.25,3-3数量的0.25面额硬币
0.5,4 - 4量的0.5面额硬币
4最后遍历地图并创建要添加到ArrayList的LineItem对象。
答案 2 :(得分:0)
尝试覆盖LineItem类中的equals ()
@Override
public boolean equals (Object obj) {
return this.getCoin.equals (((LineItem)obj).getCoin);
}
这应该允许列表中的contains ()
方法检查硬币是否已经在列表中,而不管相关数量。
答案 3 :(得分: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方法,它将比较值和名称。虽然在你的情况下只是值足够。
E.g。
public boolean equals(Coin coinToCompare) {
return value.equals(coinToCompare.getValue()) && name.equals(coinToCompare.getName());
}
如果你只是在没有覆盖equals()方法的情况下执行equals(),那么它只会进行参考比较而不是你想要的比较。
另外,我认为你最好使用带有密钥的HashMap作为硬币的值,而不是使用允许重复的列表。