如何使用Java流仅收集长度最大的元素?

如何使用Java流仅收集长度最大的元素?,java,java-stream,Java,Java Stream,我正在尝试使用Java Streams从我的列表中收集所有长度最大的字符串: List<String> strings = Arrays.asList("long word", "short", "long wwww", "llll wwww", "shr"); List<String> longest = strings.stream() .sorted(Comparator.comparingInt(String::length).rever

我正在尝试使用Java Streams从我的列表中收集所有长度最大的
字符串:

List<String> strings = Arrays.asList("long word", "short", "long wwww", "llll wwww", "shr");

List<String> longest = strings.stream()
            .sorted(Comparator.comparingInt(String::length).reversed())
            .takeWhile(???)
            .collect(Collectors.toList());
但是。。。丑陋?我不喜欢引入虚拟包装器(谢谢,实际上是最终需求)或
peek()
hack


是否有更优雅的方法来实现这一点?

您可以认为它更丑陋,但是自定义收集器确实是正确的、更有效的,甚至是很好的并行化:

Collector<String, List<String>, List<String>> collector = Collector.of(
   ArrayList::new,
   (list, elem) -> {
     if (list.isEmpty() || elem.length() == list.get(0).length()) {
       list.add(elem);
     } else if (elem.length() > list.get(0).length()) {
       list.clear();
       list.add(elem);
     }
   },
   (list1, list2) -> {
     int len1 = list1.isEmpty() ? -1 : list1.get(0).length();
     int len2 = list2.isEmpty() ? -1 : list2.get(0).length();
     if (len1 < len2) {
       return list2;
     } else if (len1 > len2) {
       return list1;
     } else {
       list1.addAll(list2);
       return list1;
     }
   });

return strings.stream().collect(collector);
Collector=Collector.of(
ArrayList::新,
(列表,元素)->{
if(list.isEmpty()| | elem.length()==list.get(0.length()){
列表。添加(元素);
}else if(elem.length()>list.get(0.length()){
list.clear();
列表。添加(元素);
}
},
(列表1、列表2)->{
int len1=list1.isEmpty()?-1:list1.get(0.length();
int len2=list2.isEmpty()?-1:list2.get(0.length();
if(len1len2){
返回列表1;
}否则{
列表1.addAll(列表2);
返回列表1;
}
});
返回strings.stream().collect(收集器);

嗯,我不知道这是否会更优雅,但它应该满足您的要求:

List strings=Arrays.asList(“长单词”、“短”、“长WW”、“llll WW”、“shr”);
List longest=strings.stream()
.collect(Collectors.groupingBy(String::length))//生成映射
.entrySet().stream()//所述映射的entrySet流
.max(Map.Entry.comparingByKey())//保持最大长度
.map(map.Entry::getValue)//获取最大长度的值
.orElse(Collections.emptyList());//如果没有,则返回一个空列表
系统输出打印项次(最长);
输出:

[long word, long wwww, llll wwww]
[long word, long wwww, llll wwww]
[long word,long ww,llll ww] 试试这个:

List strings=Arrays.asList(“长单词”、“短”、“长WW”、“llll WW”、“shr”);
List longest=strings.stream()
.collect(groupingBy(String::length,TreeMap::new,toList())
.lastEntry()
.getValue();
系统输出打印项次(最长);
输出:

[long word, long wwww, llll wwww]
[long word, long wwww, llll wwww]

我不知道你是否觉得它更优雅,但它很简洁:

       List<String> strings = Arrays.asList("long word", "short", "long wwww", "llll wwww", "shr");

       TreeMap<Integer, List<String>> collect = strings.stream().collect(
                Collectors.groupingBy(
                        String::length,
                        TreeMap::new,
                        mapping(Function.identity(), toList())));

       System.out.println(collect.lastEntry().getValue());
List strings=Arrays.asList(“长单词”、“短”、“长WW”、“llll WW”、“shr”);
TreeMap collect=strings.stream().collect(
收集者分组(
字符串::长度,
树映射::新的,
映射(Function.identity(),toList());
System.out.println(collect.lastEntry().getValue());

我认为正确性是优雅的一部分,在这种情况下,我认为这不仅是优越的,而且是一种优雅的解决方案。非常感谢。不过,如果有其他方法出现,我想等待。如果没有,我会很高兴地接受你的回答!您可能指的是
list1.get(0.length()
,而不是
list1.get(0.size()
。做了一个编辑,请随意回复。这是我一直努力的目标,谢谢!@IlyaLysenko使用
TreeMap
给出的答案是一个更优雅的版本。@Fureeish,但对于像或那样简单的东西来说过于复杂,定义自定义收集器从来没有什么坏处。对格式和TreeMap进行了一次微不足道的编辑,并不是说你的答案不正确。在我看来,它是现有功能中最干净的。@Naman,我已经把它回滚了。请用这个版本单独回答。因为它不仅使用流。您可以再看看,它确实使用
Stream
,并使用构造函数初始化
TreeMap
。为该编辑制作另一个答案没有任何附加值。这仍然符合OP的期望,并且对回滚也很好。简短而优雅,但是如果
字符串
列表为空,这会爆炸。