7

我正在寻找解决以下问题:
从集合 A 开始,我想将该集合(比如集合 B)上的某种“视图”传递给某个方法。视图 B 不一定包含原始集合 A 的所有元素。如果在此方法中将对象添加到视图(集合 B)或从视图(集合 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

一种方法是使用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);        
}

另一种更通用的方法是通过 Guavas Collections2.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 方法,以便这些操作也在源集合上执行。

IE

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 实际上应该是原始列表的代理。

或者,通过更多的工作,您可以实现 Collection 或 List 接口,以便您以类似的方式直接处理原始列表

然后,您可以调用您的方法或传递 ListView,就像普通集合一样。

IE

public void doSomeWork(Collection<String> collection);

...

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

Jacarta 集合框架具有这样的功能。但是这个框架不支持泛型。看看谷歌番石榴。我相信他们也应该支持这样的功能。

于 2012-09-05T12:37:00.897 回答
-2

你总是可以有两个不同的集合,一个集合 A 和一个集合 B。

然后,每当您向 中添加某些内容时B,您都会将其添加到 中A,并且每当从B您那里删除某些内容时,也会将其从 中删除A

A您那里删除时,将检查是否B包含要删除的对象,如果是,则将其删除。

但是,添加到 时A,您不会触摸B

这可能比最佳解决方案的空间效率低,但它不会改变时间复杂度(除了可能从A. 中删除)

于 2012-09-05T12:36:43.700 回答