从一个ArrayList中提取和修改到另一个

时间:2013-09-04 20:16:28

标签: java arraylist

我需要一个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值。

如何解决这个问题?

4 个答案:

答案 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)

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

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

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

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

  4.   

    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作为硬币的值,而不是使用允许重复的列表。