找出最便宜的项目
我还是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在运行前没有指出它。有人能指出我正确的方向吗?有没有另外一种方法可以做到这一点?
最好的解决方案是在min
方法中使用比较器,而不是null。这应该允许它得到你需要的结果 - 如果比较器不知道如何比较项目,比较器就无法获得最小值!您可以删除呼叫进行排序,并将比较器添加到min
的呼叫中。它应该是这样的:
public T cheapestItem(){
return Collections.min(items, (i1, i2) -> i1.getPrice().compareTo(i2.getPrice()));
}
如果返回最昂贵的,而不是最便宜的,只是改变你的比较顺序从t1.compareTo(t2)
到t2.compareTo(t1)
。
这在技术上是正确的。但更好的解决方案是继续使用min(),并使用正确的比较器(用于无用的sort()),并删除排序。查找最小值比排序整个列表要快,Collections.min()更清楚地表达了意图。 –
@JBNizet你说得对,会更有效 - 我编辑了我的答案。 – nhouser9
最后一部分是不必要的。这会找到最便宜的。比较器可以简化为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;
}
}
}
您正在对列表进行排序,尽管它没用,但是使用了正确的比较器。然后你调用min(),你必须这样做,但用null作为比较器。 –