7

私は次の問題を解決しようとしています:
コレクション A から始めて、そのコレクション (コレクション B など) のある種の「ビュー」を特定のメソッドに渡したいと考えています。ビュー B には元のコレクション A のすべての要素が含まれている必要はありません。このメソッドでオブジェクトがビュー (コレクション B) に追加または削除された場合、これらの変更は元のコレクション A にも反映されます。

たとえば(疑似コード):

  1. 開始状況:

    Collection A = {1, 2, 3};  
    View-on-collection B = {1, 2};
    
  2. メソッド呼び出し:

    someMethod(B) {  
        B.add(4);  
        B.remove(2);  
    }
    
  3. 終了状況:

    Collection A = {1, 3, 4};
    

この問題のきちんとした解決策を知っている人はいますか?

4

4 に答える 4

5

1つの方法は使用することList.sublist()です:

public static void main(String[] args) {
    List<Integer> aList = new ArrayList<Integer>(Arrays.asList(1,2,3));
    List<Integer> view = aList.subList(0, 2);

    view.add(new Integer(4));
    view.remove(new Integer(2));
    System.out.println("aList: " + aList);
    System.out.println("view : " + view);        
}

もう1つのより一般的な方法は、GuavasCollections2.filter()を使用することです。これにより、ビューに含めるオブジェクトを制御するための述語を定義できます。

public static void main(String[] args) {

    List<Integer> aList = new ArrayList<Integer>(Arrays.asList(1,2,3));
    @SuppressWarnings("unchecked")
    Collection<Integer> view = Collections2.filter(aList, new Predicate() {
        public boolean apply(Object arg0) {
            return ((Integer) arg0).intValue() % 3 != 0;
        }});
    view.add(new Integer(4));
    view.remove(new Integer(2));
    System.out.println("aList: " + aList);
    System.out.println("view : " + view);

}

両方の例が印刷されます

aList: [1, 4, 3]
view : [1, 4]
于 2012-09-05T12:45:31.983 に答える
0

AbstractList(または使用しているコレクションの抽象タイプ)を拡張できます。

この抽象化では、コンストラクターでソースコレクションを取得し、そのコレクションへの参照と、元のリストのビューの開始点と終了点を保持できます。

add / remove / setメソッドをオーバーライドして、これらのアクションがソースコレクションでも実行されるようにします。

すなわち

class ListView<T> extends AbstractList<T> {

   int start = 0;
   int end = 0;
   private Collection<T> original = null;

   public ListView(List<T> original, int start, int end) {
       this.original = original;
       this.start = start;
       this.end = end;
       super.addAll(0, original.subList(start, end));
   }

   // Any add/set/remove must also alter the original

}

ListViewは、事実上、元のリストのプロキシである必要があります。

または、もう少し作業を行うことで、コレクションまたはリストインターフェイスを実装して、同様の方法で元のリストを直接操作することもできます。

次に、通常のコレクションと同じように、メソッドを呼び出すか、ListViewを渡すことができます。

すなわち

public void doSomeWork(Collection<String> collection);

...

object.doSomeWork(new ListView<String>(original, 0, 2));
于 2012-09-05T12:46:37.833 に答える
0

Jacarta コレクション フレームワークにはそのような機能があります。ただし、このフレームワークはジェネリックをサポートしていません。Google Guava を見てみましょう。そのような機能もサポートする必要があると思います。

于 2012-09-05T12:37:00.897 に答える
-2

コレクション A とコレクション B の 2 つの異なるコレクションを常に持つことができます。

次に、何かを に追加するたびに に追加しBA何かを削除するたびBに からも削除しAます。

から削除するときは、削除するオブジェクトが含まれているAかどうかを確認Bし、含まれている場合は削除します。

ただし、 に追加するA場合は、 に触れませんB

これは、最適なソリューションよりもスペース効率が悪いかもしれませんが、時間の複雑さを変えることはありません (おそらく からの削除を除いてA)。

于 2012-09-05T12:36:43.700 に答える