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更容易理解。我会做出建议的修改,谢谢。在上面,我的意思是“倒装”而不是“倒装”。