根据产生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<String> 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);
}
}
答案 0 :(得分:13)
使用
String longestName = names.stream().max(Comparator.comparing(String::length)).get();
比较某些属性的元素(可能比这更复杂,但不是必须)。
As Brian suggests in the comments,如果Optional#get()
为空,则Stream
使用{{1}}是不安全的。您更适合使用其中一种更安全的检索方法,例如Optional#orElse(Object)
,如果没有最大值,它会为您提供一些默认值。
答案 1 :(得分:3)
我认为应该考虑到max
/ min
是唯一的,argMax
/ argMin
当然不能保证这一点。这特别意味着减少的类型应该是集合,例如List
。这需要比上面建议的工作多一点。
以下ArgMaxCollector<T>
类提供了这种减少的简单实现。 main
显示此类的应用程序来计算字符串集的argMax
/ argMin
one two three four five six seven
以他们的长度排序。输出(分别报告argMax
和argMin
收集器的结果)应为
[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<T> {
private T max = null;
private ArrayList<T> argMax = new ArrayList<T>();
private Comparator<? super T> comparator;
private ArgMaxCollector( Comparator<? super T> 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<T> 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<T> get() {
return argMax;
}
public static <T> Collector<T, ArgMaxCollector<T>, List<T>> collector( Comparator<? super T> comparator ) {
return Collector.of(
() -> new ArgMaxCollector<T>( 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<String> names = Arrays.asList( new String[] { "one", "two", "three", "four", "five", "six", "seven" } );
Collector<String, ArgMaxCollector<String>, List<String>> argMax = ArgMaxCollector.collector( Comparator.comparing( String::length ) );
Collector<String, ArgMaxCollector<String>, List<String>> argMin = ArgMaxCollector.collector( Comparator.comparing( String::length ).reversed() );
System.out.println( names.stream().collect( argMax ) );
System.out.println( names.stream().collect( argMin ) );
}
}
答案 2 :(得分:-1)