我正在寻求解决以下问题:
从集合A开始,我想将该集合(比如集合B)上的某种“视图”传递给某个方法。视图B不必包含原始集合A的所有元素。如果在此方法中将对象添加到视图(集合B)或从视图中删除,则这些更改也应反映在原始集合A上。
例如(伪代码):
开始情况:
Collection A = {1, 2, 3};
View-on-collection B = {1, 2};
方法调用:
someMethod(B) {
B.add(4);
B.remove(2);
}
结束情况:
Collection A = {1, 3, 4};
有谁知道这个问题的巧妙解决方案?
答案 0 :(得分:4)
一种方法是使用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]
答案 1 :(得分:0)
Jacarta集合框架具有此类功能。但是这个框架不支持泛型。看看谷歌番石榴吧。我相信他们也应该支持这样的功能。
答案 2 :(得分: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实际上应该是原始列表的Proxy。
或者,通过更多工作,您可以实现Collection或List接口,以便以类似的方式直接在原始列表上工作
然后,您可以调用您的方法或像普通集合一样传递ListView。
即
public void doSomeWork(Collection<String> collection);
...
object.doSomeWork(new ListView<String>(original, 0, 2));
答案 3 :(得分:-2)
您可以始终拥有两个不同的集合,集合A和集合B.
然后,每当您向B
添加内容时,都会将其添加到A
,每当从B
删除某些内容时,您也会将其从A
中删除。< / p>
从A
中删除时,您会检查B
是否包含要删除的对象,如果是,则删除它。
但是,添加到A
时,您不会触及B
。
这可能比最佳解决方案的空间效率更低,但它不会改变时间复杂度(除了可能从A
删除。)