关于集合的Java可修改视图

War*_*ard 7 java collections data-structures

我想解决以下问题:
从集合A开始,我想将该集合(比如集合B)上的某种"视图"传递给某个方法.视图B不必包含原始集合A的所有元素.如果在此方法中将对象添加到视图(集合B)或从视图中删除,则这些更改也应反映在原始集合A上.

例如(伪代码):

  1. 开始情况:

    Collection A = {1, 2, 3};  
    View-on-collection B = {1, 2};
    
    Run Code Online (Sandbox Code Playgroud)
  2. 方法调用:

    someMethod(B) {  
        B.add(4);  
        B.remove(2);  
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 结束情况:

    Collection A = {1, 3, 4};
    
    Run Code Online (Sandbox Code Playgroud)

有谁知道这个问题的巧妙解决方案?

Kep*_*pil 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);        
}
Run Code Online (Sandbox Code Playgroud)

另一种更通用的方法是通过 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);

}
Run Code Online (Sandbox Code Playgroud)

两个例子都打印

aList: [1, 4, 3]
view : [1, 4]
Run Code Online (Sandbox Code Playgroud)

  • 请注意,您不能向 Guava 的 `Collections2.filter()` 返回的视图添加任何值。引用 [Javadoc](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Collections2.html),“当给出一个不满足谓词,集合的 add() 和 addAll() 方法抛出 IllegalArgumentException。” 您的示例有效,因为 4 不是 3 的倍数,但如果您尝试添加 6,则会失败。 (2认同)

ebo*_*oix -2

您始终可以有两个不同的集合,集合 A 和集合 B。

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

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

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

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