简体   繁体   中英

Get elements with a certain generic type in a list

I am currently working on a train project and I have following question:

I save all rolling stock in a list: To understand my class hierarchy better, here is a simplified inheritance overview:

RollingStock
    Engine
        SteamEngine
        DieselEngine
        ...
    Coach
        FreightCoach
        PassengerCoach
        ...
    TrainSet

In my register, I want to save all rolling stock in a list private List<RollingStock> rollingStock; . So far, I have created a list for each rolling stock type (engines, coaches, trainSets). However, I need to delete a certain rolling stock with just its ID and therefore it's easier to save everything in just one list.

As of before, I created an engine like this:

    public void createEngine(Engine engine) {
        this.engines.add(engine);
    }

Now, with just one list I do it like this:

    public void createEngine(Engine engine) {
        this.rollingStocks.add(engine);
    }

This works perfectly fine. For the returnEngines() method I don't seem to find a solution:

It was as easy as this with one list for each rolling stock type:

    public List<Engine> returnEngines() {
        return engines;
    }

Now, I have to filter all engines out of the rolling stock list:

    public List<Engine> returnEngines() {
        ...
        return rollingStock.???;

    }

I could add the method public String getType() and check for its type.

I can't imagine that there isn't a better solution.

How can this be done?

Stream the list, filter for instances of Engine ; map the instances from RollingStock to Engine (with a cast), collect the results into a new List . Like,

public List<Engine> returnEngines() {
    return rollingStocks.stream().filter(x -> x instanceof Engine)
            .map(x -> (Engine) x).collect(Collectors.toList());
}

The answer from Elliott Frisch is perfectly valid, here is a generified solution, in case you need also a method to filter your register for any type of your hierarchy:

public <T> List<T> returnClazz(Class<T> clazz) {
    return rollingStocks.stream()
            .filter(clazz::isInstance)
            .map(clazz::cast)
            .collect(Collectors.toList());
}

Which then can be used by several helper methods, eg

public List<TrainSet> returnTrainset() {
    return returnClazz(TrainSet.class);
}

public List<Engines> returnEngines() {
    return returnClazz(Engine.class);
}
...

or can be called directly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM