java 是否可能有一个泛型示例列表?

6ie5vjzr  于 2023-03-21  发布在  Java
关注(0)|答案(2)|浏览(123)

我有三个包含一些字段的对象,但其中两个字段是开始日期和结束日期。
我有另一个Wrapper类,它包含两个字段(startDate和endDate)和一个构造函数。
我想创建一个泛型方法,它接受ObjectA、ObjectB、ObjectC,并返回一个包含开始日期和结束日期的时间列表。
有没有更好的方法让它更有活力?

@Data
@AllArgsConstructor
@NoArgsConstructor
public class TimeIntervalObj {

    private Timestamp startDate;
    private Timestamp endDate;

    public static List<TimeIntervalObj> constructTimeIntervals(List<?> arrayList) {
        if (arrayList instanceof ObjectA) {
            return arrayList.stream()
                    .map(ObjectA.class::cast)
                    .map(time -> new TimeIntervalObj(time.getStartDate(), time.getEndDate())).collect(Collectors.toList());
        } else if (arrayList instanceof ObjectB) {
            return arrayList.stream()
                    .map(ObjectB.class::cast)
                    .map(time -> new TimeIntervalObj(time.getStartDate(), time.getEndDate())).collect(Collectors.toList());
        } else if (arrayList instanceof ObjectC) {
            return arrayList.stream()
                    .map(ObjectC.class::cast)
                    .map(time -> new TimeIntervalObj(time.getStartDate(), time.getEndDate())).collect(Collectors.toList());
        }
        throw new RuntimeException("Instance Error Type Incompatibility");
    }

}
pjngdqdw

pjngdqdw1#

使ObjectAObjectBObjectC实现相同的接口。

interface MyObject {
    Timestamp getStartDate();
    Timestamp getEndDate();
}

这样,Stream管道就变得简单了。

return arrayList.stream()
        .filter(MyObject.class::isInstance)
        .map(MyObject.class::cast)
        .map(time -> new TimeIntervalObj(time.getStartDate(), time.getEndDate()))
        .collect(Collectors.toList());

但是,如果ObjectAObjectBObjectC对象中的每一个都需要到TimeIntervalObj对象的不同Map,那么较新的Java版本提供了一个带有密封类和开关表达式的解决方案:
一个一个二个一个一个一个三个一个一个一个一个一个一个四个一个一个一个一个一个五个一个

**实现注意事项:**您可以在启用预览的情况下使用Java 17,否则只需要使用简单的if-else分支和instanceof运算符。

8ftvxx2r

8ftvxx2r2#

简单的方法是引入一个新的接口来定义getStartDate()getEndDate()方法,并让ObjectAObjectBObjectC实现它:

public interface HasStartAndEndDate {
    Timestamp getStartDate();
    Timestamp getEndDate();
}

那么你的方法可以简单地是:

public static List<TimeIntervalObj> constructTimeIntervals(Collection<? extends HasStartAndEndDate> arrayList) {
    return arrayList.stream()
            .map(time -> new TimeIntervalObj(time.getStartDate(), time.getEndDate()))
            .collect(Collectors.toList());
}

如果出于某种原因这不可行(很可能是因为任何一个类都不在您的控制之下),那么您可能必须单独检查每个对象类型:

public static List<TimeIntervalObj> constructTimeIntervals(Collection<?> collection) {
    return collection.stream()
            .map(TimeIntervalObj::from)
            .collect(Collectors.toList());
}

public static TimeIntervalObj from(Object o) {
    if (o instanceof ObjectA a) {
        return new TimeIntervalObj(a.getStartDate(), a.getEndDate());
    } else if (o instanceof ObjectB b) {
        return new TimeIntervalObj(b.getStartDate(), b.getEndDate());
    } else if (o instanceof ObjectC c) {
        return new TimeIntervalObj(c.getStartDate(), c.getEndDate());
    }
    throw new IllegalArgumentException("Unsupported type: " + o.getClass());
}

如果你想让你控制下的所有类都使用这个接口,并且其他类也被支持,这两种方法也可以结合使用(假设ObjectAObjectB现在实现了这个接口,但是ObjectC仍然没有实现):

public static List<TimeIntervalObj> constructTimeIntervals(Collection<?> collection) {
    return collection.stream()
            .map(TimeIntervalObj::from)
            .collect(Collectors.toList());
}

public static TimeIntervalObj from(HasStartAndEndDate hsed) {
    return new TimeIntervalObj(hsed.getStartDate(), hsed.getEndDate());
}

public static TimeIntervalObj from(Object o) {
    if (o instanceof HasStartAndEndDate hsed) {
        return from(hsed);
    } else if (o instanceof ObjectC c) {
        return new TimeIntervalObj(c.getStartDate(), c.getEndDate());
    }
    throw new IllegalArgumentException("Unsupported type: " + o.getClass());
}

请注意,额外的from(HasStartEndDate)方法不是绝对必要的(并且不会在constructTimeIntervals中直接调用,因为编译器会理解参数的类型为Object),但最好避免在静态类型已知的情况下使用instanceof方法(例如,如果在代码的其他地方直接调用TimeIntervalObj.from(someKnownObjectThatImplementsHasStartEndDate))。

相关问题