Reputation: 33
I have three lists in my program.
The lists were declared as so:
ONE = external source
TWO = ONE
THREE = ONE
I have this issue when responding to the user filtering specific items. The function will iterate over THREE and List.remove(index) items that match the filtered item. The function does not interact with TWO. Despite this TWO is modified to be equivalent to THREE despite the initial declarations not being run again (I checked with the debugger and can't work out when TWO is ever modified).
I tried changing TWO to be a Collections.unmodifiableList() but it was still modified?
I fixed the issue with some serious jankiness.
Object[] temp = new Object[ONE.size()];
temp=ONE.toArray(temp);
TWO = Arrays.asList(temp);
Awful I know... It works because Arrays.asList is immutable but surely the unmodifiable list is also immutable?
Added Code for those requesting. Initialisation Code:
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);
}
Responding to removing or adding items.
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);
}
Upvotes: 3
Views: 86
Reputation: 82599
If you have code like this
List<Object> ONE = someMagic();
List<Object> TWO = ONE;
List<Object> THREE = ONE;
Then you have three things all pointing at the same list.
If you want them to be different, you could try something like this:
List<Object> ONE = someMagic();
List<Object> TWO = ONE.clone();
List<Object> THREE = ONE.clone();
This way they make actual different lists.
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);
}
So to fix this, you need to remove the dependency on that backing array
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"
}
if clone
is not available for you, you can do it a little more complicated
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"
}
Upvotes: 2
Reputation: 719709
I tried changing TWO to be a
Collections.unmodifiableList()
but it was still modified?
The javadocs say this about unmodifiable views as created by that method:
An unmodifiable view collection is a collection that is unmodifiable and that is also a view onto a backing collection. Its mutator methods throw
UnsupportedOperationException
, as described above, while reading and querying methods are delegated to the backing collection. The effect is to provide read-only access to the backing collection. ...Note that changes to the backing collection might still be possible, and if they occur, they are visible through the unmodifiable view. Thus, an unmodifiable view collection is not necessarily immutable.
In short, unmodifiableList()
does not have the properties that you expect. If you want an immutable snapshot of a mutable list, you need to copy it.
Upvotes: 1