I am trying to use Java Streams to collects all the String
s of the greatest length from my list:
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());
I would like my longest
to contain {"long word", "long wwww", "llll wwww"}
, because those are the String
s that have the greatest lengths. In case of only having one of the String
s with greatest length, I am obviously expecting the resulting List
to contain only that element.
I tried to first sort them in order to have the greatest length appear in the first element, but I am unable to retrieve the length of the first element in the stream. I could try something like 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);
}
but it's... ugly? I don't like the introduction of dummy wrapper (thank you, effectively final requirement) or the peek()
hack.
Is there any more elegant way to achieve this?
Try this:
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);
Output:
[long word, long wwww, llll wwww]
Well, I don't know if this will be more elegant but it should do what you want:
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);
Output:
[long word, long wwww, llll wwww]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With