Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List<Base> to List<Long> ... conditional cast

Lets say I have those 3 classes (strongly reduced) :

public interface Base
{
    String getType();
}

public class Object1 implements Base
{
    String getType() { ... };

    long getSerialNr() { ... };
}

public class Object2 implements Base
{
    String getType() { ... };

    long getPartNr() { ... };
}

How would I (using Java 8 streams) convert a List<Base> to a List<Long> using conditional casts? I started with this:

List<Long> result = baseList.stream().filter(Objects::nonNull)
    .filter(Object1.class::isInstance)
    .map(Object1.class::cast)
    .map(o -> o.getSerialNr())
    .collect(Collectors.toList());

...but how can I integrate the second case, where the element is an instance of Object2 and I want to return getPartNr?

like image 534
paddy3k Avatar asked Nov 25 '25 18:11

paddy3k


1 Answers

Assuming that the number of classes may grow, you may have to abstract the mapping of type to property:

static Map<Predicate<Base>,Function<Base,Long>> ACCESSORS;
static {
    Map<Predicate<Base>,Function<Base,Long>> m=new HashMap<>();
    m.put(Object1.class::isInstance, base -> ((Object1)base).getSerialNr());
    m.put(Object2.class::isInstance, base -> ((Object2)base).getPartNr());
    ACCESSORS=Collections.unmodifiableMap(m);
}
static Stream<Long> get(Base b) {
    return ACCESSORS.entrySet().stream()
            .filter(e -> e.getKey().test(b))
            .map(e -> e.getValue().apply(b));
}

The get method assumes that the predicates are mutual exclusive, which is the case when testing for these non-interface types.

Then, you can use it like:

List<Long> result = baseList.stream()
    .flatMap(YourClass::get)
    .collect(Collectors.toList());

You could also inline the get method, but that’s not improving the readability:

List<Long> result = baseList.stream()
    .flatMap(b -> ACCESSORS.entrySet().stream()
        .filter(e -> e.getKey().test(b))
        .map(e -> e.getValue().apply(b)))
    .collect(Collectors.toList());
like image 63
Holger Avatar answered Nov 28 '25 16:11

Holger



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!