0

内部的にデータのリストを格納するクラスがあるとしましょう。

import java.util.List;

public class Wrapper
{
    private List<Integer> list;

    public Wrapper(List<Integer> list)
    {
        this.list = list;
    }

    public Integer get(int index) { return list.get(index); }
}

この例のために、それが有用で必要な抽象化であると偽ってください。さて、ここに私の懸念があります:このクラスの基礎となる実装を知っているプログラマーとして、コンストラクターで要求するリストのタイプについて具体的にする必要がありますか?実証するために、私はこのテストを行いました:

import java.util.List;
import java.util.ArrayList;
import java.util.LinkedList;

public class Main
{
    public static void main(String[] args)
    {
        long start;
        List<Integer> list1 = new ArrayList<Integer>();
        List<Integer> list2 = new LinkedList<Integer>();
        Wrapper wrapper1, wrapper2;

        for(int i = 0; i < 1000000; i++)
        {
            list1.add(i);
            list2.add(i);
        }

        wrapper1 = new Wrapper(list1);
        wrapper2 = new Wrapper(list2);

        start = System.currentTimeMillis();

        wrapper1.get(500000);

        System.out.println(System.currentTimeMillis() - start);

        start = System.currentTimeMillis();

        wrapper2.get(500000);

        System.out.println(System.currentTimeMillis() - start);
    }
}

ご存知かもしれませんが、リンクリストでは、配列ではなく、要素にランダムにアクセスするのに少し時間がかかります。では、Wrapperコンストラクターに戻ると、一般的で任意のタイプのリストを許可する必要がありますか、それともユーザーがArrayListを渡して、可能な限り最高のパフォーマンスを確保するように指定する必要がありますか?この例では、メソッドgetの基本的な実装が何であるかをユーザーが推測するのは簡単かもしれませんが、これはもっと複雑なことであると想像できます。前もって感謝します!

4

5 に答える 5

3

インターフェースの要点は、基礎となる実装について不可知論を可能にすることです。LinkedList や ArrayList とは対照的に List 型を使用すること自体が、この種の問題を心配することなく一般的な操作を可能にすることです。List によって公開されていないメソッドに依存せずにコードを記述できる限り、心配する必要はありません。

このクラスのユーザーは、使用するリストの種類に他の要件があるコードを書いている可能性があります。たとえば、LinkedList が優れている場合、リストの途中に多くを追加している可能性があります。そのため、可能な限り最も一般的な型を受け入れ、ユーザーがその型を使用する正当な理由があると想定する必要があります。

ただし、これは、アプリケーションの他の使用法に違いがない場合、ArrayList の使用が優れている可能性があるという javadoc コメントを含めることを止めるものではありません。

于 2009-06-10T00:06:33.087 に答える
2

では、Wrapper コンストラクターに戻ると、一般的であり、あらゆるタイプのリストを許可する必要がありますか?

ラッパーの意図は、任意のタイプのリストをサポートすることですか? またはArrayListのみ?

...または、可能な限り最高のパフォーマンスを確保するために、ユーザーが ArrayList を渡すように指定する必要がありますか?

一般的なリストをそのままにしておくと、問題ありません。そのクラスの「クライアント」に、ArrayList を使用できるかどうかを決定させます。クライアント次第です。

意図を反映するためにRandomAccessインターフェースを使用することもできますが、これは単なるマーカー インターフェースであるため、おそらくあまり意味がありません。

繰り返しますが、一般的なリストのままにしておくだけで十分です。

于 2009-06-10T00:37:32.697 に答える
0

このリストからランダムにアクセスする場合、またはこのリストに大量に追加すると思われる場合は、ArrayList を使用してください。

ほとんどの場合、一連の要素にアクセスする場合は、LinkedList を使用してください。

于 2009-06-10T00:12:38.893 に答える
0

Wrapperクラスで何を達成しようとしているのか、および/またはクライアントがそれを何に使用することを期待しているかに依存すると思いますWrapper

Listクライアントが特定のレベルのパフォーマンスを期待すべきではない(またはメソッドの名前が何であれ)のラッパーを提供するだけの場合get()、クラスはそのままで問題ないように見えますが、それがlistリスト自体の内容ではなく、コピーされるコンストラクターのパラメーターへの参照にすぎません (これについては、以下の 3 番目のポイントで詳しく説明します)。

ただし、クライアントにget()非常に応答性が高いことを期待するように伝える場合は、いくつかの代替案が思い浮かびます (他にもあるかもしれません)。

  1. Listどのような操作を実行してもパフォーマンスが高いことがわかっているの実装のみを受け入れる一連のコンストラクターを記述しますget()。例えば:

} // このブレースを回避する方法を知っていれば...

 public Wrapper {
     Wrapper(ArrayList<Integer> list) { ... }
     Wrapper(KnownListImplementationThatWillMakeMyGetMethodFast<Integer> list) { ... }

     //...
 } 

これを行うことの 1 つの欠点は、別の効率的なList実装が登場した場合、別のコンストラクターを追加する必要があることです。

  1. クラスはそのままにしておきますWrapperが、(クラス コメントや README ファイルなどの何らかの形式のドキュメントを介して) クライアントに、List渡された実装に対する特定の操作には特定のパフォーマンスが期待されることを伝えます (たとえば、"get()は一定時間」)。彼らが a を渡してラッパーを「誤用」した場合LinkedList、それは彼らのせいです。

  2. 実装が迅速であることを保証したい場合get()は、コンストラクターで受け取ったリストを、パフォーマンスの制約を満たすメンバー データ構造にコピーすることをお勧めします。これはArrayList、あなたが知っている他のList実装、またはインターフェイスを完全に実装していないコンテナList(たとえば、あなたが書いた特別な目的) である可能性があります。の内容をコピーすることと、それへの参照をコピーすることについて先に述べたことに関して、あなたが持っている参照に対して実行する「書き込み」操作は、その内容をコピーする場合List、クライアントの のコピーには流れません。Listこれは通常、クライアントが、クライアントで操作を呼び出すときにリストのコピーが変更される理由を不思議に思うのを避ける良い方法です。Wrapper、この動作を期待するように明示的に指示しない限り。

于 2009-06-10T00:43:01.267 に答える
0

これはおそらく議論できることです。

特定のタイプを要求するための私の議論は次のとおりです。

  • ラッピング クラスは、ラッピング クラスが使用されるすべての状況でどのタイプが最適かを実際に認識しています。ランダム アクセスは、この良い例です。配列。
  • ラッピング クラスは、実際には実装について想定しています。そのような仮定が行われる場合は、適切な型を要求することによってそれらが満たされることを確認してください。

特定のタイプを要求することに対する議論は次のとおりです。

  • ラッピング クラスはさまざまなシナリオで使用され、特定のシナリオに多かれ少なかれ適したさまざまな List の実装があります。つまり、シナリオに最も適した実装を見つけるのは、呼び出し元次第です。また、ラッパー クラスが作成されるまでに、List の最適な (TM) 実装がまだ発明されていない場合もあります。
于 2009-06-10T00:07:04.473 に答える