2016-11-02 60 views
1

我還是Java和Eclipse的新手。我應該通過泛型類在列表中找出最便宜的項目並打印出它的參數。我有這樣的:找出最便宜的項目

public class Store<T extends Item>{ 

public List<T> items = new ArrayList<T>(); 

public void addItem(T it){ 
     items.add(it); 
} 

public T cheapestItem(){ 
     T cheapest; 

     Collections.sort(items, (i1, i2) -> i1.getPrice().compareTo(i2.getPrice())); 

     cheapest = Collections.min(items,null); 

     return cheapest; 

} 


} 

在我的主要活動:

Store<Item> store = new Store<>(); 

for (int i = 0; i < items.size(); i++) { 
      store.addItem(items.get(i).getA()); 
      store.addItem(items.get(i).getB()); 
} 

System.out.println("Cheapest item price is " + store.cheapestItem().getPrice()); 

我得到一個錯誤信息:

Exception in thread "main" java.lang.ClassCastException: com.java.school.B cannot be cast to java.lang.Comparable 
at java.util.Collections.min(Unknown Source) 
at java.util.Collections.min(Unknown Source) 
at com.java.school.Store.cheapestItem(Store.java:20) 
at com.java.school.Main.main(Main.java:313) 

不幸的是,我不知道我做錯了,因爲Eclipse在運行前沒有指出它。有人能指出我正確的方向嗎?有沒有另外一種方法可以做到這一點?

+0

您正在對列表進行排序,儘管它沒用,但是使用了正確的比較器。然後你調用min(),你必須這樣做,但用null作爲比較器。 –

回答

2

最好的解決方案是在min方法中使用比較器,而不是null。這應該允許它得到你需要的結果 - 如果比較器不知道如何比較項目,比較器就無法獲得最小值!您可以刪除呼叫進行排序,並將比較器添加到min的呼叫中。它應該是這樣的:

public T cheapestItem(){ 
    return Collections.min(items, (i1, i2) -> i1.getPrice().compareTo(i2.getPrice())); 
} 

如果返回最昂貴的,而不是最便宜的,只是改變你的比較順序從t1.compareTo(t2)t2.compareTo(t1)

+1

這在技術上是正確的。但更好的解決方案是繼續使用min(),並使用正確的比較器(用於無用的sort()),並刪除排序。查找最小值比排序整個列表要快,Collections.min()更清楚地表達了意圖。 –

+0

@JBNizet你說得對,會更有效 - 我編輯了我的答案。 – nhouser9

+0

最後一部分是不必要的。這會找到最便宜的。比較器可以簡化爲Comparator.comparing(Item :: getPrice)。 –

-1

您的例外顯示T必須執行Comparable才能使用方法Collections.min。你在編輯器中「證明」(並確保它是真實的)在你未顯示的Item的定義中。聲明Item implements Comparable並確保在那裏有一個compareTo方法。

0

我會做的是創建一個局部變量,它存儲最便宜的物品找到並遍歷列表。

public T cheapestItem() { 
    T cheapest = items.get(0); 
    for (T item : items) { 
     if (item.getPrice() < cheapest.getPrice()) { 
      cheapest = item; 
     } 
    } 
} 
相關問題