2009-08-06 16 views
0

これはJavaの質問です。リストを変換する最速の方法<?><ObjectType>

List<?>List<ObjectType>に変換する最も簡単な方法は何ですか?私はこれが反復によって可能であることを認識しています。そのオプションを除外してください。反復によって

例、

final List<ObjectType> targetList = new ArrayList<ObjectType>(); 
// API returns List<?> so I have no choice. 
List<?> resultList = resultSet.getResults(); 

// This is slow. Average list size is 500,000 elements. 
while (resultList != null && !resultList.isEmpty()) { 
    for (final Object object : resultList) { 
     final ObjectType objectType = (ObjectType) object; 
     targetList.add(objectType); 
    } 
    resultSet = someService.getNext(resultSet); 
    resultList = resultSet.getList(); 
} 

感謝。

+1

あなたはアレイベースのリストを使用しているので、あなたが事前に割り当て50万要素試みた(約限りまたは?)。これにより、パフォーマンスが向上する可能性があります。 –

+0

私はそれについて考えるので、LinkedListは全体の "事前割り当てメモリ"問題を完全に排除します。 –

+1

'resultList'から要素を取り除くものがありますか、' while'は 'if'ですか? –

答えて

5

それは少し怖いですが、状況に応じて、あなたはおそらくちょうどキャストで逃げることができます:

final List<ObjectType> targetList = (List<ObjectType>)problemSolver.getResults(); 
+0

この問題については、私もその解決策を検討します。 –

+0

一般に、これは型セーフではありません。 –

+0

これは間違いありませんが、使用されているAPIを使用することはできません。 – Tom

1

あなたが本当に50万要素を扱うと、パフォーマンスの問題をexpreriencingしている場合はうーん、私は弾丸をかむ(弾丸がコンパイラの「未チェック」の警告である)と、それをキャストしたい:

List<ObjectType> targetList = new ArrayList<ObjectType>((List<ObjectType>) resultList); 

あなたは@SuppressWarnings( "unchecked")アノテーションを使用して警告を抑制することができます。

上記はもちろん、​​が何らかの形であなたを満たしていないと仮定しています(おそらく、それは変更不可能であるか、アレイバックであるか、何がありますか)。それ以外の場合は、単にキャストすることができます。

1

正解はあなたがtargetListに入れる要素が本当にObjectTypeのインスタンスであることを確実にしたいかどうかに依存します(またはサブタイプ)。

気にしない場合は、安全でないタイプキャストを使用するソリューションの1つになります。あなたがコピーする必要がない限り、@トムのソリューションが良いです。 getResults()がリンクリストを返し、アルゴリズムがtargetList.get(int)を多く使用する必要がある場合は、コピーする必要があります)。ただし、仮定が正しくない場合は予期しないClassCastExceptionが発生する可能性があります。

間違った型の要素がないことを確認する必要がある場合は、getResults()がどのようなタイプのListタイプを提供しているかわからない限り、イテレータベースのソリューションを使用する必要があります。 (あなたがgetResults()ArrayListの結果をキャストすることができた場合は、get(int)を使用してインデックスを作成することはIteratorを使用するよりも高速にする必要があります。一方で、結果は、リストがO(N**2)でコピーするget(int)を使用して、LinkedListであれば!!)

これはいかがですか?

final List<?> resultList = problemSolver.getResults(); 

List<ObjectType> targetList; 
if (resultList == null || resultList.isEmpty()) { 
    targetList = Collections.empyList(); 
} else { 
    int len = resultList.size(); 
    // it is important to preallocate the ArrayList with the 
    // right size ... to conserve space and avoid copy on realloc 
    // of the list's private backing array. 
    targetList = new ArrayList<ObjectType>(len); 
    if (resultList instanceof ArrayList) { 
     // Copy using indexing - O(N) for ArrayLists 
     ArrayList<?> arrayList = (ArrayList) resultList; 
     for (int i = 0; i < len; i++) { 
      targetList.add((ObjectType) (arrayList.get(i))); 
     } 
    } else { 
     // Copy using iterator - O(N) for all sane List implementations, 
     // but with a larger C than the best case for indexing. 
     for (Object obj : resultList) { 
      targetList.add((ObjectType) obj); 
     } 
    } 
} 
0

繰り返しにはどのような問題がありますか?

しかし、あなたが望むように:

final List<?> src = ...; 
final int len = src.size(); 
final SomeType[] dstArray = new SomeType[len]; 
src.<SomeType>toArray(dstArray); 
final List<SomeType> dst = java.util.Arrays.asList(dstArray); 

または:

私は反復法を好む(免責事項コンパイルそんなにないと。)。

+0

Umm .. 'src.toArray()'はコピーを作成しませんか?だから二重コピーを終わらせる。 –

+0

はい、それは物事のスキーム(まだ 'LinkedList'よりも優れています!)では大きな問題ではありません。私は 'toArray'引数が奇妙な境界を持っているのを忘れていました。 –

2

上記のように、元のList<?>のすべてがObjectTypeであることを知っていれば、反復コードで暗示されているように、List<ObjectType>にキャストするとうまくいきます。

反復コードからの唯一の違いは、ときに」何でもあなたは、targetListを移入しているときClassCastExceptionが起こる反復コードにないObjectType、まっすぐなキャストとの間に、それが起こるだろうならば、ということです値を取り戻す。例えば:

public static void main(String[] args) { 
    List<?> list = Arrays.<Object> asList('I', "am", "not", "homogeneous"); 
    List<Character> targetList = (List<Character>) list; 

    int index = 0; 
    try { 
     for (Character c : targetList) { 
      System.out.println(c); 
      index++; 
     } 
    } finally { 
     System.out.println("Reached " + index); 
    } 
} 

プリント

I 
Exception in thread "main" java.lang.ClassCastException: java.lang.String 
cannot be cast to java.lang.Character 
    at Foo.main(Foo.java:100) 
Reached 1 
関連する問題