过滤器列表包含多个对象java



下面的代码现在对我来说很好,但它不是未来的证明,因为if elseinstanceof的数量。我想用更多的对象来扩展传输列表,比如biyles、motors等……但每次添加新对象时,我都需要添加更多的if else语句并创建更多的instanceof。有人有更好的想法或更好的解决方案吗?

private static Transport filterObjects(List<Transport> listOfTransport, int refNr) {
List<Transport> cars = listOfTransport.stream()
.filter(transport -> transport instanceof Cars)
.collect(Collectors.toList());

List<Transport> airPlanes = listOfTransport.stream()
.filter(transport -> transport instanceof Airplanes)
.collect(Collectors.toList());

if (!cars.isEmpty()){
return cars.get(refNr);
} else if (!airPlanes.isEmpty()) {
return airPlanes.get(refNr);
} else {
return null;
}
}

传入所需的子类型。也许这会奏效:

private static Transport filterObjects(List<Transport> listOfTransport, Class clazz, int refNr) {
List<Transport> transports = listOfTransport.stream().filter(clazz::isInstance).collect(Collectors.toList());

return !transports.isEmpty() ? transports.get(refNr) : null;
}

正如你目前优先考虑汽车而不是飞机一样,随着交通类型的增加,你也需要某种优先权才能优先返回。你可以用枚举来解决这个问题。您只需要在添加新的传输类型后立即相应地扩展枚举。枚举可能看起来像:

enum Priority{
Car(1), 
Airplane(2);

private int value;
Priority (int value) {
this.value = value;
}
public int getValue() {
return value;
}
}

然后,您可以重构您的方法,方法是根据列表中的元素的简单类名对其进行分组,并使用您在枚举中定义的优先级将它们添加到排序映射中。然后,您可以使用映射的第一个条目来确定返回值。示例:

private static Transport filterObjects(List<Transport> listOfTransport, int refNr) {
Comparator<String> comp = Comparator.comparingInt(e -> Priority.valueOf(e).getValue());

List<Transport> result = 
listOfTransport.stream()
.collect(Collectors.groupingBy(
e -> e.getClass().getSimpleName(), 
() -> new TreeMap<>(comp), 
Collectors.toList()))
.firstEntry().getValue();

return (result != null && 0 <= refNr && refNr < result.size()) ? 
result.get(refNr) : null;        
}

首先根据子类型将列表元素分组到映射中,然后创建传输的子类型列表。重复此列表,然后检查地图中是否存在相应的条目:


private static final List<Class> subTypes = List.of(Cars.class, Airplanes.class);
private static Transport filterObjects(List<Transport> listOfTransport, int refNr) {
Map<Class, List<Transport>> map = listOfTransport.stream()
.collect(Collectors.groupingBy(t -> t.getClass()));

Optional<List<Transport>> op = subTypes.stream()
.filter(map::containsKey)
.findFirst();
if(op.isPresent()) {
return op.get().get(refNr); // This could cause IndexOutOfBoundsException
}else{    
return null;
}
}

好吧,您可以执行以下操作。

首先,定义您的订单:

static final List<Class<? extends Transport>> ORDER = List.of(
Car.class,
Airplane.class
);

然后,您可以编写以下方法:

private static Transport filterObjects(List<Transport> listOfTransport, int refNr) {
Map<Class<? extends Transport>, Transport> map = listOfTransport.stream()
.collect(Collectors.groupingBy(Transport::getClass, Collectors.collectingAndThen(Collectors.toList(), list -> list.get(refNr))));
return ORDER.stream()
.filter(map::containsKey)
.map(map::get)
.findFirst()
.orElse(null);
}

这样做的目的是将每个不同的Class映射到作为相应类的子类型的第refNr个元素。

然后,它遍历ORDER并检查是否在原始listOfTransport中找到了元素。如果listOfTransport不包含特定类的任何元素,则键将不存在于映射中。


注意,如果映射中存在特定类的任何元素,则该类的元素数至少为refNr,否则抛出IndexOutOfBoundsException。换句话说,每次传输必须在listOfTransport内发生0次或至少refNr次。

还要注意,getClass()不一定产生与instanceof相同的结果。然而,我在这里假设每个相应的传输都没有进一步的子类。

相关内容

  • 没有找到相关文章

最新更新