Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/359.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 获取列表中具有特定泛型类型的元素_Java_Generics_Inheritance - Fatal编程技术网

Java 获取列表中具有特定泛型类型的元素

Java 获取列表中具有特定泛型类型的元素,java,generics,inheritance,Java,Generics,Inheritance,我目前正在从事一项列车项目,我有以下问题: 我将所有机车车辆保存在列表中: 为了更好地理解我的类层次结构,下面是一个简化的继承概述: RollingStock Engine SteamEngine DieselEngine ... Coach FreightCoach PassengerCoach ... TrainSet 在我的登记簿中,我想将所有机车车辆保存在一个列表私有

我目前正在从事一项列车项目,我有以下问题:

我将所有机车车辆保存在列表中: 为了更好地理解我的类层次结构,下面是一个简化的继承概述:

RollingStock
    Engine
        SteamEngine
        DieselEngine
        ...
    Coach
        FreightCoach
        PassengerCoach
        ...
    TrainSet
在我的登记簿中,我想将所有机车车辆保存在一个列表
私有列表rollingStock中。到目前为止,我已经为每种机车车辆类型(发动机、客车、列车组)创建了一个列表。但是,我需要删除一个只有其ID的特定机车车辆,因此更容易将所有内容保存在一个列表中

在之前,我创建了一个如下的引擎:

    public void createEngine(Engine engine) {
        this.engines.add(engine);
    }
    public void createEngine(Engine engine) {
        this.rollingStocks.add(engine);
    }
现在,只要一个列表,我就可以这样做:

    public void createEngine(Engine engine) {
        this.engines.add(engine);
    }
    public void createEngine(Engine engine) {
        this.rollingStocks.add(engine);
    }
这个很好用。对于returnEngines()方法,我似乎没有找到解决方案:

就这么简单,每种机车车辆类型都有一个列表:

    public List<Engine> returnEngines() {
        return engines;
    }
公共列表返回引擎(){
回程发动机;
}
现在,我必须过滤机车车辆列表中的所有发动机:

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

    }
公共列表返回引擎(){
...
返回滚动轴承座。???;
}
我可以添加方法
公共字符串getType()
并检查其类型

我无法想象没有更好的解决办法


如何做到这一点?

流式处理列表,过滤
引擎的实例;将实例从
RollingStock
映射到
Engine
(使用强制转换),将结果收集到新的
列表中。像

public List<Engine> returnEngines() {
    return rollingStocks.stream().filter(x -> x instanceof Engine)
            .map(x -> (Engine) x).collect(Collectors.toList());
}
公共列表返回引擎(){
返回rollingStocks.stream().filter(引擎的x->x实例)
.map(x->(引擎)x).collect(收集器.toList());
}

Elliott Frisch的回答完全正确,这里是一个通用的解决方案,以防您还需要一种方法来过滤您的寄存器以获得任何类型的层次结构:

public <T> List<T> returnClazz(Class<T> clazz) {
    return rollingStocks.stream()
            .filter(clazz::isInstance)
            .map(clazz::cast)
            .collect(Collectors.toList());
}
public List returnClazz(类clazz){
返回rollingStocks.stream()
.filter(clazz::isInstance)
.map(clazz::cast)
.collect(Collectors.toList());
}
然后可以由几个辅助方法使用,例如

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

public List<Engines> returnEngines() {
    return returnClazz(Engine.class);
}
...
public List returnTrainset(){
返回CLAZZ(车组.班);
}
公共列表返回引擎(){
返回clazz(引擎类);
}
...

或者可以直接调用。

您的股票列表中的股票顺序是否有价值?如果没有,我认为您最好使用
Set
s。我的另一个建议是,如果你想要收集发动机和机车车辆(等),你可以将机车车辆作为一个合成集合,由其他集合内部组成。使用
Set
有什么好处?它将如何解决我的问题?首先,你可以使用Set自动防止重复。另一方面,确认对象在集合中可以更快。第三件事是,如果您不需要对组合的集合定义顺序,则可以更轻松地将基础集合(蒸汽引擎集合、柴油发动机集合)组合到单个集合中。这有助于解决您的问题吗?使用一组基础集合,您可以将该集合用于所有RollingStock上的操作,但是当您只需要引擎时,您可以使用该集合,而不必按照Frisch的回答进行过滤谢谢,这将解决我的问题。例如,当我列出所有列车时(通过其ID),我仍然可以对一组列车进行排序吗?如何合并我的所有集合?MergeSets()只能用于合并两个集合,对吗?集合定义为无序,排序没有任何意义。您可以使用List.addAll(…)将集合中的所有内容添加到列表中以进行排序。至于合并,我建议您创建一个类来实现
Set
,并使用属于较大
Set
的其他集合来实现
Set
s方法。谢谢,但是使用instanceof是一种糟糕的编码风格,不是吗?我可以改用getClass()或isInstance()吗?在运行时检查类型是不好的,与编码风格无关
.filter(Engine.class::isInstance)
也可以工作(但实际上与我发布的内容相同)。