2013-09-04 6 views
0

Мне нужен один ArrayList<Coin> выберите уникальные элементы и добавьте в другое ArrayList<LineItem>. LineItem содержит монету и количество совпадений этой монеты в первом списке.Извлечь и изменить от одного ArrayList к другому

Мой код работает, но не правильно, и я не знаю, как обойти это ограничение?

Вот чек выход:

// 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 полдоллара и количество доллара список 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; 
} 

Он добавляет последний элемент to itemsList coz Этот список не содержит элемент с количеством == 1. Но этот список имеет то же значение Coin.

Как решить эту проблему?

+5

Я не понимаю, в чем проблема. –

+0

В 'while (! Done & i <= itemsList.size())' лучше использовать 'while ((! Done) && (i <= itemsList.size()))' –

+0

@tieTYT список элементов LineItem содержит элементы с тем же именем монеты и разным количеством. Для этого элемента должна быть увеличена quntity. –

ответ

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()); 

, но это не будет работать если вы не отказываетесь Coin#hashCode

+0

Можете ли вы показать решение карты? –

+0

Добавлен ответ –

0

Я хотел бы предложить еще один подход к достигнутым этой цели:

  1. переопределить метод Equals в классе монет, таким образом, что он возвращает истина/ложь на основе стоимости монет.

  2. итерация через массив, добавьте каждую монету определенного значения в карте с ключом как номинал монеты и ценность, как количество (like [0.25, 1]; [0.5, 2])

  3. держать на подведение ваших количеств и заменить значение конкретного наименования в эта карта; таким образом, что в конце карты выглядит следующим образом:

0,25, 3 - 3 Количество 0,25 номинал монеты

0,5, 4 - 4 Количество 0,5 номинал монеты

4 На пройдите по карте и создайте объект LineItem для добавления в ArrayList.

0

Попробуйте перекрывая equals() в классе LineItem

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

Это должно позволить contains() метод в списке, чтобы проверить, если монета уже в списке, независимо от соответствующего количества.

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]] 

Если бы я был вами, чтобы решить проблему, я бы применил метод equals на Coin, который бы сравнивал как значение, так и имя. Хотя в вашем случае просто значение выглядит достаточно.

E.g.

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

Если вы просто сделать Equals() без overidding Равных() метода, то это будет просто сделать эталонное сравнение, а не сравнение, как вы хотите.

Кроме того, я думаю, что вам лучше использовать HashMap с ключом в качестве значения монеты, а не использовать список, который позволит дублировать.

Смежные вопросы