我正在尝试使用 Java StreamsString从我的列表中收集最大长度的所有s:
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());
Run Code Online (Sandbox Code Playgroud)
我希望 mylongest包含{"long word", "long wwww", "llll wwww"},因为那些是String具有最大长度的s。如果只有String最大长度的s之一,我显然希望结果List只包含该元素。
我试图首先对它们进行排序,以便在第一个元素中出现最大长度,但我无法检索流中第一个元素的长度。我可以尝试类似的东西peek():
static class IntWrapper {
int value;
}
public static void main(String[] args) throws IOException {
List<String> strings = Arrays.asList("long word", "short", "long wwww", "llll wwww", "shr");
IntWrapper wrapper = new IntWrapper();
List<String> longest = strings.stream()
.sorted(Comparator.comparingInt(String::length).reversed())
.peek(s -> {
if (wrapper.value < s.length()) wrapper.value = s.length();
})
.takeWhile(s -> s.length() == wrapper.value)
.collect(Collectors.toList());
System.out.println(longest);
}
Run Code Online (Sandbox Code Playgroud)
但它……丑吗?我不喜欢引入 dummy wrapper(谢谢,实际上是最终要求)或peek() hack。
有没有更优雅的方法来实现这一目标?
尝试这个:
List<String> strings = Arrays.asList("long word", "short", "long wwww", "llll wwww", "shr");
List<String> longest = strings.stream()
.collect(groupingBy(String::length, TreeMap::new, toList()))
.lastEntry()
.getValue();
System.out.println(longest);
Run Code Online (Sandbox Code Playgroud)
输出:
[long word, long wwww, llll wwww]
Run Code Online (Sandbox Code Playgroud)
好吧,我不知道这是否会更优雅,但它应该做你想做的:
List<String> strings = Arrays.asList("long word", "short", "long wwww", "llll wwww", "shr");
List<String> longest = strings.stream()
.collect(Collectors.groupingBy(String::length)) // Build Map<Length, List<Strings>>
.entrySet().stream() // EntrySet stream of said map
.max(Map.Entry.comparingByKey()) // Keep max length
.map(Map.Entry::getValue) // Get value of max length
.orElse(Collections.emptyList()); // Or return an empty list if there's none
System.out.println(longest);
Run Code Online (Sandbox Code Playgroud)
输出:
[长词,长 wwww,llll wwww]
您可能认为它更丑陋,但自定义收集器绝对正确、更高效,甚至可以很好地并行化:
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);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
374 次 |
| 最近记录: |