找出最便宜的项目

问题描述:

我还是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作为比较器。 –

最好的解决方案是在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)。 –

您的例外显示T必须执行Comparable才能使用方法Collections.min。你在编辑器中“证明”(并确保它是真实的)在你未显示的Item的定义中。声明Item implements Comparable并确保在那里有一个compareTo方法。

我会做的是创建一个局部变量,它存储最便宜的物品找到并遍历列表。

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