如何使用Java流仅收集长度最大的元素?
我正在尝试使用Java Streams从我的列表中收集所有长度最大的如何使用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
字符串:
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的期望,并且对回滚也很好。简短而优雅,但是如果字符串列表为空,这会爆炸。