Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/347.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_Subclass - Fatal编程技术网

Java 使集合均匀化

Java 使集合均匀化,java,generics,subclass,Java,Generics,Subclass,假设我有一个非泛型的列表或列表,您知道所有元素的类型都是Bar,这是Foo的一个子类(总是这样)。假设您无法更改获取原始列表的代码,以便直接获取列表。是否有一些库或其他东西可以帮助“同质化”这个列表 也就是说,有没有一个功能在静脉的 public static <T, U extends T> List<U> homogenize(List<T> list, Class<U> subclass); 公共静态列表同质化(列表列表,类子类); 我可

假设我有一个非泛型的
列表
列表
,您知道所有元素的类型都是
Bar
,这是
Foo
的一个子类(总是这样)。假设您无法更改获取原始列表的代码,以便直接获取
列表。是否有一些库或其他东西可以帮助“同质化”这个列表

也就是说,有没有一个功能在静脉的

public static <T, U extends T> List<U> homogenize(List<T> list, Class<U> subclass);
公共静态列表同质化(列表列表,类子类);

我可以在什么地方用?(
uniformize()
返回输入列表的视图,其中函数采用
U
,而不是
T
对象
。它不返回列表的副本。如果无法均匀化输入列表,也就是说,如果不是所有元素的类型都可分配给U,则
uniformize()
返回null。)

为什么不能直接强制转换它

public static <U> List<U> homogenize(List<? super U> list){
    return (List<U>)list;
}

公共静态列表同质化(List如果您正在寻找一个库,我的第一个想法是使用以下方法:

public <T, U extends T> List<U> homogenize(List<T> list, final Class<U> subclass) {
    Predicate<T> pred = new Predicate<T>() {
        @Override
        public boolean apply(T input) {
            return input.getClass().isAssignableFrom(subclass);
        }
    };
    return Iterables.all(list, pred) ? (List<U>)list : null;
}
公共列表同质化(列表列表,最终类子类){
谓词pred=新谓词(){
@凌驾
公共布尔应用(T输入){
返回input.getClass().isAssignableFrom(子类);
}
};
返回Iterables.all(list,pred)?(list)list:null;
}
我还没有试过,以确保扭结是正确的。但是,我看了看,觉得它非常难看。稍微好一点的番石榴方法是:

public <T, U extends T> List<U> homogenize(List<T> list, Class<U> subclass) {
    Iterable<U> ret = Iterables.filter(list, subclass);
    if (list.size() != Lists.newArrayList(ret).size()) return null;
    return (List<U>)list;
}
公共列表同质化(列表列表,类子类){
Iterable ret=Iterables.filter(列表,子类);
if(list.size()!=Lists.newArrayList(ret.size())返回null;
返回(列表)列表;
}
但是,它仍然有点难看。它使用集合的内部副本。它仍然返回原始集合的强制转换视图。说到底,最干净的方法似乎是使用常规Java:

public <T, U extends T> List<U> homogenize(List<T> list, Class<U> subclass) {
    for( T t : list) {
        if (!t.getClass().isAssignableFrom(subclass)) return null;
    }
    return (List<U>)list;
}
公共列表同质化(列表列表,类子类){
对于(T:列表){
if(!t.getClass().isAssignableFrom(subclass))返回null;
}
返回(列表)列表;
}
根据您对类型转换警告的厌恶程度,您甚至可以在所有三个选项中删除类型转换操作符

根据评论进行编辑 评论中提出了以下更改/改进

改进的备选方案一:

public <T, U extends T> List<U> homogenize(List<T> list, final Class<U> subclass) {
    return Iterables.all(list, Predicates.instanceOf(subclass)) ? (List<U>)list : null;
}
public <T, U extends T> List<U> homogenize(List<T> list, Class<U> subclass) {
    Iterable<U> ret = Iterables.filter(list, subclass);
    return (list.size() != Iterables.size(ret)) ? null : (List<U>)list;
}
public <T, U extends T> List<U> homogenize(List<T> list, Class<U> subclass) {
    for( T t : list) {
        if (!subclass.isInstance(t.getClass())) return null;
    }
    return (List<U>)list;
}
公共列表同质化(列表列表,最终类子类){
返回Iterables.all(list,谓词.instanceOf(subclass))?(list)list:null;
}
改进的备选方案二:

public <T, U extends T> List<U> homogenize(List<T> list, final Class<U> subclass) {
    return Iterables.all(list, Predicates.instanceOf(subclass)) ? (List<U>)list : null;
}
public <T, U extends T> List<U> homogenize(List<T> list, Class<U> subclass) {
    Iterable<U> ret = Iterables.filter(list, subclass);
    return (list.size() != Iterables.size(ret)) ? null : (List<U>)list;
}
public <T, U extends T> List<U> homogenize(List<T> list, Class<U> subclass) {
    for( T t : list) {
        if (!subclass.isInstance(t.getClass())) return null;
    }
    return (List<U>)list;
}
公共列表同质化(列表列表,类子类){
Iterable ret=Iterables.filter(列表,子类);
return(list.size()!=Iterables.size(ret))?null:(list)list;
}
改进的备选方案三:

public <T, U extends T> List<U> homogenize(List<T> list, final Class<U> subclass) {
    return Iterables.all(list, Predicates.instanceOf(subclass)) ? (List<U>)list : null;
}
public <T, U extends T> List<U> homogenize(List<T> list, Class<U> subclass) {
    Iterable<U> ret = Iterables.filter(list, subclass);
    return (list.size() != Iterables.size(ret)) ? null : (List<U>)list;
}
public <T, U extends T> List<U> homogenize(List<T> list, Class<U> subclass) {
    for( T t : list) {
        if (!subclass.isInstance(t.getClass())) return null;
    }
    return (List<U>)list;
}
公共列表同质化(列表列表,类子类){
对于(T:列表){
if(!subclass.isInstance(t.getClass())返回null;
}
返回(列表)列表;
}

通过这些改进,第一个Guava示例非常出色。如果您不介意静态导入,这两个Guava示例都会变得非常可读。

不使用isAssignableFrom,您就不能强制转换每个元素并捕获ClassCastException以返回null吗?这只会在编译时帮助您。在运行时,它可能会失败。@KevinWelker:您可以向后调用
isAssignable()
,但更简单的是,您可以执行
子类.isInstance(input)
,或者更简单地使用Guava的
谓词.instanceOf(subclass)
。在第二种方法中,您可以使用
Iterables.size()
而不是创建副本。但是一旦你使用了
谓词.instanceOf()
,我认为第一种方法是非常清楚的。无论你喜欢它还是纯粹的命令式方法都是一个品味问题:-)@FrankPavageau,我认为subclass.isIntance(parentClass)是parentClass.isAssignableFrom(subclass)的反义词,所以我认为我所展示的是相同的——尽管不可否认,isInstance更容易理解。我会做出建议的修改,谢谢。在上面,我的意思是“倒装”而不是“倒装”。