4

非ジェネリックListまたは がありList<Foo>、すべての要素が のBarサブクラスである 型であることがわかっているとしますFoo(これは常に当てはまります)。直接取得できるように、元のリストを取得するコードを変更できないと仮定しますList<Bar>。このリストを「均質化」するのに役立つライブラリやその他のものはありますか?

つまり、の静脈に機能がありますか

public static <T, U extends T> List<U> homogenize(List<T> list, Class<U> subclass);

どこかで使える?(は、適切な場所ではなく、または適切な場所homogenize()で受け取る関数を使用して、入力リストのビューを返します。リストのコピーは返しません。入力リストを均質化できない場合、つまり、すべての要素が代入可能な型ではない場合U の場合、null を返します。)UTObjecthomogenize()

4

2 に答える 2

4

ライブラリを探している場合、私が最初に考えたのは、次のようにGoogle Guava Librariesを使用することでした。

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;
}

ねじれが出ていることを確認するために、まだ試していません。しかし、私はそれを見て、かなりお尻が醜いと判断しました。わずかに優れたグアバのアプローチは次のとおりです。

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;
}

しかし、それはまだ少し醜いです。また、コレクションの内部コピーを使用します。元のキャスト ビューは引き続き返されます。結局のところ、最もクリーンなアプローチは通常の 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;
}

型キャストの警告に対する嫌悪感によっては、3 つのオプションすべてでキャスト演算子を削除することもできます。

コメントごと の編集 次の変更/改善がコメントで提案されました。

オプション 1 の改善:

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;
}

オプション 2 の改善:

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;
}

オプション 3 の改善:

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;
}

これらの改善により、最初の Guava の例はかなり輝いています。静的インポートを気にしなければ、どちらの Guava の例も非常に読みやすくなります。

于 2012-08-28T04:32:08.897 に答える
0

なぜあなたはそれをキャストできないのですか?

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

ジェネリックは純粋にコンパイル時のチェックであることに注意してください。型が期待どおりでない場合、 ではないオブジェクトを にキャストしようとすると、例外が発生しbarますbar

編集:実際にコンテンツのタイプをチェックし、失敗した場合に null を返すようにしたいことに気づきませんでした。アイテムが適切なタイプであり、フェイルファストの動作が必要であることが確実にわからない場合は、他のアプローチのいずれかを使用することをお勧めします。

于 2012-08-28T01:40:06.103 に答える