首页 > 解决方案 > 尽管是 Collections.unmodifiableList(),但 Java List 被从某处修改

问题描述

我的程序中有三个列表。

列表是这样声明的:

ONE = 外部来源

二 = 一

三=一

响应用户过滤特定项目时,我遇到了这个问题。该函数将遍历与过滤项匹配的三个和 List.remove(index) 项。该函数不与 TWO 交互。尽管最初的声明没有再次运行,但这两个被修改为等同于三个(我用调试器检查过,当两个被修改时无法解决)。

我尝试将 TWO 更改为 Collections.unmodifiableList() 但它仍然被修改?

我用一些严重的问题解决了这个问题。

Object[] temp = new Object[ONE.size()];
temp=ONE.toArray(temp);
TWO = Arrays.asList(temp);

糟糕,我知道......它之所以有效,是因为 Arrays.asList 是不可变的,但不可修改的列表肯定也是不可变的?

为请求者添加了代码。初始化代码:

protected void onPostExecute(List<SpaceObject> visibleObjects){
    hideLoading();
    SpaceObject[] atom = new SpaceObject[visibleObjects.size()];
    atom=visibleObjects.toArray(atom);
    VISIBLE_OBJECTS = Arrays.asList(atom);
    SHOWING_OBJECTS = visibleObjects;
    addToView(visibleObjects);
}

响应删除或添加项目。

private void showSpecificItems(String itemType, Boolean remove){
    int i = 0;

    if (remove) {
        while (i < SHOWING_OBJECTS.size()){
            if(SHOWING_OBJECTS.get(i).getType().toLowerCase().matches(itemType.toLowerCase())){
                    SHOWING_OBJECTS.remove(i);
            }else{
                i++;
            }
        }
    }else{
        System.out.println("remove");
        while(i < VISIBLE_OBJECTS.size()){
            if(VISIBLE_OBJECTS.get(i).getType().toLowerCase().matches(itemType.toLowerCase())){
                SHOWING_OBJECTS.add(VISIBLE_OBJECTS.get(i));
            }
            i++;
        }
        SHOWING_OBJECTS = sortBrightest(SHOWING_OBJECTS);
    }
    addToView(SHOWING_OBJECTS);

}

标签: javaandroidlistimmutability

解决方案


如果你有这样的代码

List<Object> ONE = someMagic();

List<Object> TWO = ONE;

List<Object> THREE = ONE;

然后你有三个东西都指向同一个列表。

如果你想让它们不同,你可以尝试这样的事情:

List<Object> ONE = someMagic();

List<Object> TWO = ONE.clone();

List<Object> THREE = ONE.clone();

通过这种方式,他们制作了实际不同的列表。

protected void onPostExecute(List<SpaceObject> visibleObjects){
    hideLoading();
    // this line is useless - you allocate an array only to immediately toss it away?!
    SpaceObject[] atom = new SpaceObject[visibleObjects.size()]; 
    atom=visibleObjects.toArray(atom);
    // this uses atom as its backing array, which comes from visibleObjects
    VISIBLE_OBJECTS = Arrays.asList(atom);
    // this obviously atom as a backing array
    SHOWING_OBJECTS = visibleObjects;
    addToView(visibleObjects);
}

所以要解决这个问题,您需要删除对该支持数组的依赖

protected void onPostExecute(List<SpaceObject> visibleObjects){
    hideLoading();

    VISIBLE_OBJECTS = visibleObjects.clone();
    SHOWING_OBJECTS = visibleObjects.clone();

    addToView(visibleObjects); // probably bad form, but I doubt this will keep a reference, so it's "acceptable"
}

如果clone不适合你,你可以做得更复杂一点

protected void onPostExecute(List<SpaceObject> visibleObjects){
    hideLoading();

    VISIBLE_OBJECTS = new ArrayList(visibleObjects);
    SHOWING_OBJECTS = new ArrayList(visibleObjects);

    addToView(visibleObjects); // probably bad form, but I doubt this will keep a reference, so it's "acceptable"
}

推荐阅读