1

特定のコレクションを「述語」でフィルタリングし、フィルタリングされた要素 (述語が true を返すもの) のみを含む新しいコレクションを返すメソッドを作成しています。

このようなもの :

    public <T> Collection<T> filter(Collection<T> collection, Closure<T> predicate);

Collection()Java では、型消去のために、実行時にnew を作成することはできません。

T.newInstance() を呼び出すメソッドに追加の引数を渡すことによる「回避策」も知っています。

これは次のようになります。

    public <T> Collection<T> filter(Class<? extends Collection<T>> collectionToInstanciate, Collection<T> collection, Closure<T> predicate) {

        // create the new Collection
        Collection<T> container = collectionToInstanciate.newInstance();

        // and then add only filtered items
        Iterator<T> iter = collection.iterator();
        while (iter.hasNext()) {
            T obj = iter.next();

            // if Predicate.invoke() returns true, then keep element, otherwise skip it
            if (predicate.invoke(obj)) {
                container.add(obj);
            }
        }
        return container;
    }

しかし、どのようにメソッドを呼び出す必要がありますか?

たとえば、整数のリストの奇数のみが必要な場合は、次のようにします。

    // instanciate ArrayList<Integer> = [1, 2, 3, 4, 5]
    ArrayList<Integer> array = ...;

    // return a new LinkedList<Integer> with only odd numbers
    filter(LinkedList<Integer>.class, array, new Closure<Integer>() {
        public Boolean invoke(Integer arg_p) {
            return (arg_p % 2 == 0);
        }
    });

    // should return [2, 4] as a LinkedList<Integer>

問題はそれです

    LinkedList<Integer>.class 

コンパイルされません。

filter() メソッドで LinkedList を正しくインスタンス化するには、どのように宣言すればよいですか?

よろしく、

4

2 に答える 2

3

ジェネリックはコンパイル時の機能であり、実行時にはほとんど意味がありません。LinkedList を作成したい場合は、それを行います。実行時に行ったことに基づいて、コンパイラにエラーを発生させることはできません。

より簡単な解決策は、入力するクラスのインスタンスを渡すことです。

List<Integer> result = filter(new LinkedList<Integer>(), array, 
    new Predicate<Integer>() {
        public boolean invoke(Integer arg_p) {
            return (arg_p % 2 == 0);
        }
    });

わずかに短く、コンパイル時にチェックできます。

注: これらの述語の多くは、単純なループよりもはるかに単純で高速です。

List<Integer> result = new LinkedList<Integer>();
for(Integer i: array)
    if (i % 2 == 0)
        result.add(i);
于 2013-06-04T21:11:44.403 に答える
0

Peter Lawrey の回答と LuiggiMendoza のコメントからの別の方法は、次のように filter() メソッドを使用することです。

    List<Integer> result = filter(
        LinkedList.class, // instead of new LinkedList<Integer>()
        array, 
        new Predicate<Integer>() {
            public boolean invoke(Integer arg_p) {
                return (arg_p % 2 == 0);
            }
        });

そして、filter() メソッドで:

    public <T> Collection<T> filter(Class<? extends Collection> collectionToInstanciate, Collection<T> collection, Closure<T> predicate) {

    // create the new Collection as a raw Collection, and cast it back to Collection<T>
    Collection<T> container = (Collection<T>) collectionToInstanciate.newInstance();

    // and then add only filtered items
    Iterator<T> iter = collection.iterator();
    while (iter.hasNext()) {
        T obj = iter.next();

        // if Predicate.invoke() returns true, then keep element, otherwise skip it
        if (predicate.invoke(obj)) {
            container.add(obj);
        }
    }
    return container;
}
于 2013-06-05T12:04:52.240 に答える