假设我们有一个项目集合:
class Item {
public String title;
public int price;
}
List<Item> list = getListOfItems();
我想从Guava库中获取一个具有最大价格的物品(我猜是Ordering)。我的意思是类似于这个Groovy代码:
list.max{it.price}
我该怎么做?效率如何?
答案 0 :(得分:57)
Ordering<Item> o = new Ordering<Item>() {
@Override
public int compare(Item left, Item right) {
return Ints.compare(left.price, right.price);
}
};
return o.max(list);
它尽可能高效:它遍历列表中的项目,并返回具有最大价格的第一个项目:O(n)。
答案 1 :(得分:37)
根据JB的回答,在使用具有自然顺序的值时,您也可以使用一些简写,例如:
Ordering.<Integer> natural().max(listOfIntegers);
有关详细信息,请参阅Ordering.natural()。
答案 2 :(得分:13)
你可以在没有番石榴的情况下做到这一点。
集合提供了对任何集合进行操作的min
和max
方法,包括使用比较器的重载。这里我们使用带有lambda的Java 8 Comparator静态方法来简明地指定比较器,但在Java 8之前,您可以使用匿名类:
Item max = Collections.max(list, Comparator.comparingInt(i -> i.price));
如果集合为空,这些方法将抛出NoSuchElementException。
Java 8流提供min
和max
函数作为比较器。这些函数返回Optional<T>
以正常处理流为空的流。 Comparator中的静态方法对于简明地指定比较器非常有用,包括自然排序的常见情况。对于这个问题,你可以使用
Optional<Item> max = list.stream().max(Comparator.comparingInt(i -> i.price));
这适用于任何流源,包括所有Collection实现,以及文件等其他内容,并且可以通过过滤流来轻松计算集合子集的最大值。如果您有一个大型集合和一个昂贵的比较器(例如,String的自然排序),您可以使用并行流。
(除此之外:理想情况下Stream会提供min
和max
重载,当流类型实现Comparable时不带参数。不幸的是,Java不支持基于类型参数有条件地暴露方法,并且它不是不值得为这种情况引入一个新的StreamOfComparable接口,扩展Stream。)