Java 8流中的arg max?

我经常需要根据产生double或int值的标准的最大化来收集集合的最大元素。 Streams有max()函数,需要我实现一个比较器,我觉得很麻烦。 是否有更简洁的语法,例如以下示例中的names.stream().argmax(String::length)

 import java.util.Arrays; import java.util.Comparator; import java.util.List; public class ArgMax { public static void main(String[] args) { List names = Arrays.asList("John","Joe","Marilyn"); String longestName = names.stream().max((String s,String t)->(Integer.compare(s.length(),t.length()))).get(); System.out.println(longestName); } } 

使用

 String longestName = names.stream().max(Comparator.comparing(String::length)).get(); 

比较一些属性上的元素(可能比这更复杂,但不必)。

正如Brian在评论中建议的那样,如果Stream可能是空的,那么使用Optional#get()是不安全的。 您更适合使用其中一种更安全的检索方法,例如Optional#orElse(Object) ,如果没有max,它将为您提供一些默认值。

我认为应该考虑到max / min是唯一的,这当然不能保证argMax / argMin ; 这特别意味着减少的类型应该是集合,例如List 。 这需要比上面建议的工作多一点。

以下ArgMaxCollector类提供了这种减少的简单实现。 main显示了这类的应用程序来计算字符串集的argMax / argMin

 one two three four five six seven 

按其长度排序。 输出(分别报告argMaxargMin收集器的结果)应该是

 [three, seven] [one, two, six] 

分别是两个最长和三个最短的字符串。

这是我第一次尝试使用新的Java 8流API,所以任何评论都会受到欢迎!

 import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.List; import java.util.stream.Collector; class ArgMaxCollector { private T max = null; private ArrayList argMax = new ArrayList(); private Comparator comparator; private ArgMaxCollector( Comparator comparator ) { this.comparator = comparator; } public void accept( T element ) { int cmp = max == null ? -1 : comparator.compare( max, element ); if ( cmp < 0 ) { max = element; argMax.clear(); argMax.add( element ); } else if ( cmp == 0 ) argMax.add( element ); } public void combine( ArgMaxCollector other ) { int cmp = comparator.compare( max, other.max ); if ( cmp < 0 ) { max = other.max; argMax = other.argMax; } else if ( cmp == 0 ) { argMax.addAll( other.argMax ); } } public List get() { return argMax; } public static  Collector, List> collector( Comparator comparator ) { return Collector.of( () -> new ArgMaxCollector( comparator ), ( a, b ) -> a.accept( b ), ( a, b ) ->{ a.combine(b); return a; }, a -> a.get() ); } } public class ArgMax { public static void main( String[] args ) { List names = Arrays.asList( new String[] { "one", "two", "three", "four", "five", "six", "seven" } ); Collector, List> argMax = ArgMaxCollector.collector( Comparator.comparing( String::length ) ); Collector, List> argMin = ArgMaxCollector.collector( Comparator.comparing( String::length ).reversed() ); System.out.println( names.stream().collect( argMax ) ); System.out.println( names.stream().collect( argMin ) ); } } 
Interesting Posts