Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I filter a Stream<T> by element's class an get a Stream<U> in one step? [duplicate]

Lets say I have

class Dog extends Animal {}
class Cat extends Animal {}

And I have a list of Animals Using Guava FluentIterable I can filter and convert in one step

List<Cat> cats = FluentIterable.from(animals)
    .filter(Cat.class)
    .toList();

Using Java8 I need to do

List<Cat> cats = animals.stream()
     .filter(c -> c instanceof Cat)
     .map(c -> (Cat) c)
     .collect(Collectors.toList());

There is no way I can make the filter & map in one step, right?

like image 319
Pablo Grisafi Avatar asked Jun 24 '15 01:06

Pablo Grisafi


1 Answers

The map step is unnecessary at runtime (it simply does nothing), you need it just to bypass the type checking during the compilation. Alternatively you can use dirty unchecked cast:

List<Cat> cats = ((Stream<Cat>) (Stream<?>) animals.stream().filter(
        c -> c instanceof Cat)).collect(Collectors.toList());

Unfortunately there's no standard way to do this in single step, but you may use third-party libraries. For example, in my StreamEx library there's a select method which solves this problem:

List<Cat> cats = StreamEx.of(animals).select(Cat.class).toList();
like image 116
Tagir Valeev Avatar answered Oct 13 '22 05:10

Tagir Valeev