如何从Guava中的List获取max()元素

Mik*_*cki 37 java guava

假设我们有一个项目集合:

class Item {
    public String title;
    public int price;
}

List<Item> list = getListOfItems();
Run Code Online (Sandbox Code Playgroud)

我想从Guava库中获得一个具有最大价格的物品(订购,我推测).我的意思是类似于这个Groovy代码:

list.max{it.price}
Run Code Online (Sandbox Code Playgroud)

我怎么做?效率如何?

JB *_*zet 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);
Run Code Online (Sandbox Code Playgroud)

它尽可能高效:它遍历列表中的项目,并返回具有最大价格的第一个项目:O(n).


小智 37

根据JB的回答,在处理具有自然顺序的值时,您还可以使用一些简写,例如:

Ordering.<Integer> natural().max(listOfIntegers);
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅Ordering.natural().


Jef*_*oom 13

没有番石榴你就可以做到这一点.

集合提供minmax操作任何集合的方法,包括带有比较器的重载.这里我们使用带有lambda的Java 8 Comparator静态方法来简明地指定比较器,但在Java 8之前,您可以使用匿名类:

Item max = Collections.max(list, Comparator.comparingInt(i -> i.price));
Run Code Online (Sandbox Code Playgroud)

如果集合为空,这些方法将抛出NoSuchElementException.


Java 8流提供minmax带有比较器的功能.这些函数返回Optional<T>以正常处理流为空.Comparator中的静态方法对于简明地指定比较器非常有用,包括自然排序的常见情况.对于这个问题,你可以使用

Optional<Item> max = list.stream().max(Comparator.comparingInt(i -> i.price));
Run Code Online (Sandbox Code Playgroud)

这适用于任何流源,包括所有Collection实现,以及文件等其他内容,并且可以通过过滤流来轻松计算集合子集的最大值.如果您有一个大型集合和一个昂贵的比较器(例如,String的自然排序),您可以使用并行流.

(旁白:理想情况下min,max当流类型实现Comparable时,Stream将提供和重载不带参数.不幸的是,Java不支持基于类型参数有条件地公开方法,并且不值得为此引入一个新的StreamOfComparable接口扩展Stream案件.)