2012-01-28 5 views
4

私はこの(簡単にするために、整数を想定)のような方法がある場合:正しい種類のリストを返すにはどうすればいいですか?

public static List<Integer> doSomething(List<Integer> list) { 
    // logic here 
} 

を、私は内部的に私が作成し、何とか移入し、呼び出し元に戻ります新しいリストを作成するために、私の処理のために必要な、呼び出し元がどのタイプのリストを渡したかわからないので、どうすればいいですか?私は、呼び出し側が渡されたどのようなことを異なる種類のListを返すようにしたくない

例えば呼び出し元がLinkedListを渡し、I を返さない場合は、ArrayListを返します。

この問題に最も近づくにはどうすればよいですか?

+0

なぜ、同じ種類のものを返す必要があるのですか?人々は 'ArrayList a = doSomething(a);'のようなものでこれを呼び出さないでしょうか?その場合、自動的にキャストされますか? – kba

+0

なぜ 'ArrayList a ='で呼び出すのですか?答えた他の友人は、どこにでも浮動小数点型のArrayListがあることを不平にして/指摘しました(つまり、インターフェイスを使用します)。 – Cratylus

+2

@KristianAntonsenそれは意味をなさない;私が 'LinkedList'を渡すと、戻り値をランダムに任意の実装にキャストできず、動作することを期待できません。 –

答えて

4

あなただけの、あなたがRandomAccessインタフェースが実装はO(1)getの操作を可能にすることを示すことを意味する

if (inputList instanceof RandomAccess) { 
    // use an ArrayList 
} else { 
    // use a LinkedList. 
} 

を行うことができ、これらの二つの出力タイプのいずれかを使用して逃げることができます。

Listで使用されるマーカーインターフェイスで、高速(ほぼ一定の時間)ランダムアクセスをサポートしていることを示します。このインタフェースの主な目的は、ジェネリックアルゴリズムがランダムアクセスリストまたはシーケンシャルアクセスリストのいずれかに適用されたときに良好なパフォーマンスを提供するように動作を変更できるようにすることです。

このようにすることで、APIによってクライアントは入力を守ることができます。彼らはCollections.unmodifiableList(...)の結果を渡すことができ、他のコードによって変更されていないことを確認してください。

実際に入力が変更可能なリストであることがわかっている場合は、リストclone()、次にclear()です。 ArrayListLinkedListの両方には、公開されている公開方法clone()があります。

+0

私は考えましたが、 'List'は' clone() 'を提供していません。 – Cratylus

+0

@ user384706、あなたの入力がパブリッククローンメソッドを持つことがわかっている場合、' clone'メソッドはリフレクティブにアクセスできます。 –

+0

私はこの解決策が好きです。しかし、それは、ユーザーが変更不可能なリストを渡す場合、このメソッドはunmodifiableListも返しますか?そして、これが望ましい行動であれば、渡されたリストが変更不可能かどうかをどうやって決めるのですか? – user949300

7

実装を特定の実装Listに結び付けるべきではありません。インターフェイスを使用するという考え方は、外部からは、それがどのような具象クラスをインスタンス化しているかは関係ありません。 Listインターフェイス。

EDIT:

とにかく、ここで可能な方法があります:

List<Integer> lst1 = new ArrayList<Integer>(); 
Class<?> klass1 = lst1.getClass(); 
List<Integer> copy1 = (List<Integer>) klass1.newInstance(); 
System.out.println(copy1.getClass().getName()); 
> java.util.ArrayList 

List<Integer> lst2 = new LinkedList<Integer>(); 
Class<?> klass2 = lst2.getClass(); 
List<Integer> copy2 = (List<Integer>) klass2.newInstance(); 
System.out.println(copy2.getClass().getName()); 
> java.util.LinkedList 

コンソールで見ることができるように、コピーは元のリストと同じクラスのインスタンスです。

あなたがタイプで渡されたのリストを作成する Class.newInstanceを使用することができ
+0

私はあなたが言っていることを強調していますが、例えば 'List'を使うのが一般的ですが、デフォルトでは' ArrayList'というアンダーネスがあると仮定しています(私の心配はどこかClassCastExceptionです) – Cratylus

+0

リストの実装を入れ替えることは、 。 – Cratylus

+0

一部の実装では、特定のタイプのリストが期待されますが、特にランダムアクセスリストがあります。 –

0

public static List<Integer> doSomething(List<Integer> list) 
{ 
    List<Integer> newList = null; 
    try 
    { 
     newList = list.getClass().newInstance(); 
    } 
    catch(InstantiationException e) 
    { 
     throw new RuntimeException(e); 
    } 
    catch(IllegalAccessException e) 
    {  
     throw new RuntimeException(e); 
    } 

    //Logic here 

    return newList; 
} 

@Test 
public void test() 
{  
    List<Integer> testList = new ArrayList<Integer>(); 

    List<Integer> resultList = doSomething(testList); 
    Assert.assertEquals(testList.getClass(), resultList.getClass()); 
    Assert.assertNotSame(LinkedList.class, resultList.getClass()); 

    testList = new LinkedList<Integer>(); 

    resultList = doSomething(testList); 
    Assert.assertEquals(testList.getClass(), resultList.getClass()); 
    Assert.assertNotSame(ArrayList.class, resultList.getClass());  
} 
+0

私はちょうど非常に似たようなものを投稿(削除)しました。 @Mike Samuelが指摘しているように、クライアントが変更不可能なラッパーを渡すとうまくいくわけではありません。 – user949300

+0

@ user949300:修正不可能なラッパーが使用される可能性がある場合は、Mike Samuelsの解決方法をお勧めします。 – esaj

0

あなたは本当に、本当に出てくる、私はメソッドのパラメータとしてあることが含まれるオブジェクトの種類を気にしている場合、同様に:

<T extends List<Integer>> T doSomething(Class<T> returnType,List<Integer> v) 
    throws Exception 
{ 
    // constructors for your return will be tricky :) 
    // returnType.newInstance() will probably work. 
    T result = returnType.newInstance(); 
    result.add(86); result.add(99); 
    return result; 
} 
1

最も良いことは、メソッドからリストの作成を削除することです。呼び出し元にリストの作成方法を決定させる:

public static void doSomething(List<Integer> dest, List<Integer> src) { 
+0

私はこのアプローチが好きです。メソッドのnewInstanceに依存するよりも優れています。 –

関連する問題