I was wondering if there was a way to simplify this? I
The stream way is probably not what you need for your requirement and your code is actually simple.
Streams allow to pass from an input (Stream<Foo>
) to a result (Foo
, List<String>
...) thanks to multiple intermediary operations (filter, map, reduce, stream a collected result...).
Each stream operation relies on the returned stream of the next operation :
To simplify it would give a chain :
a -> b (use a)-> c (uses b)-> d (uses c)-> e (uses d)
Actually you code cannot rely on such a logic because the returned List<String>
doesn't need only to return the list of names that have duplicates, that could be written such as :
List<String> duplicates =
animals.stream()
.collect(Collectors.groupingBy(Animal::getName))
.entrySet().stream()
.filter(e -> e.getValue().size() > 1)
.map(Entry::getKey)
.collect(Collectors.toList());
you want return a List
of each duplicate appearition in the order these occur.
It means that you don't map Stream<Animal>
-> Stream<String>
such as
a->b (uses a)
because you need to filter out the element if the Animal name was not added in the result ... but a stream is not designed to populate incrementally the result. So you are stuck.
You could write this one but as said that is really not a simplification and still it doesn't apply the same logic as the order of dup names is not the same as in your code :
List<String> duplicates =
animals.stream()
.collect(Collectors.groupingBy(Animal::getName, LinkedHashMap::new, Collectors.toList()))
.values().stream()
.flatMap(l-> l.stream().skip(1))
.map(Animal::getName)
.collect(Collectors.toList());