Fix to SetUniqueList breaks when swapping entries

bug 33294, from Tom Dunham

git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/collections/trunk@149033 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Stephen Colebourne 2005-01-29 12:51:12 +00:00
parent 1da9c06f4d
commit 560c4ee8db
3 changed files with 147 additions and 8 deletions

View File

@ -54,6 +54,7 @@ There are no new deprecations.
<li>BoundedFifoBuffer/CircularFifoBuffer - Fix serialization to work in case where buffer serialized when full [31433]</li>
<li>BoundedFifoBuffer - Fix iterator remove bug causing ArrayIndexOutOfBounds error [33071]</li>
<li>MultiHashMap.remove(key, item) - Was returning the item even when nothing was removed [32366]</li>
<li>SetUniqueList.set(int,Object) - Destroyed set status in certain circumstances [33294]</li>
</ul>
<center><h3>JAVADOC</h3></center>

View File

@ -1,5 +1,5 @@
/*
* Copyright 2001-2004 The Apache Software Foundation
* Copyright 2001-2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -35,6 +35,7 @@ import org.apache.commons.collections.set.UnmodifiableSet;
* This implementation breaks these in certain ways, but this is merely the
* result of rejecting duplicates.
* Each violation is explained in the method, but it should not affect you.
* Bear in mind that Sets require immutable objects to function correctly.
* <p>
* The {@link org.apache.commons.collections.set.ListOrderedSet ListOrderedSet}
* class provides an alternative approach, by wrapping an existing Set and
@ -43,10 +44,11 @@ import org.apache.commons.collections.set.UnmodifiableSet;
* This class is Serializable from Commons Collections 3.1.
*
* @since Commons Collections 3.0
* @version $Revision: 1.8 $ $Date: 2004/06/03 22:02:13 $
* @version $Revision: 1.8 $ $Date$
*
* @author Matthew Hawthorne
* @author Stephen Colebourne
* @author Tom Dunham
*/
public class SetUniqueList extends AbstractSerializableListDecorator {
@ -198,7 +200,7 @@ public class SetUniqueList extends AbstractSerializableListDecorator {
* The object is set into the specified index.
* Afterwards, any previous duplicate is removed
* If the object is not already in the list then a normal set occurs.
* If it is present, then the old version is removed and re-added at this index
* If it is present, then the old version is removed.
*
* @param index the index to insert at
* @param object the object to set
@ -206,11 +208,16 @@ public class SetUniqueList extends AbstractSerializableListDecorator {
*/
public Object set(int index, Object object) {
int pos = indexOf(object);
Object result = super.set(index, object);
Object removed = super.set(index, object);
if (pos == -1 || pos == index) {
return result;
return removed;
}
return remove(pos);
// the object is already in the uniq list
// (and it hasn't been swapped with itself)
super.remove(pos); // remove the duplicate by index
set.remove(removed); // remove the item deleted by the set
return removed; // return the item deleted by the set
}
public boolean remove(Object object) {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2001-2004 The Apache Software Foundation
* Copyright 2001-2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -18,6 +18,7 @@ package org.apache.commons.collections.list;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
@ -29,9 +30,10 @@ import junit.textui.TestRunner;
* JUnit tests.
*
* @since Commons Collections 3.0
* @version $Revision: 1.6 $ $Date: 2004/06/02 22:07:53 $
* @version $Revision: 1.6 $ $Date$
*
* @author Matthew Hawthorne
* @author Tom Dunham
*/
public class TestSetUniqueList extends AbstractTestList {
@ -275,6 +277,135 @@ public class TestSetUniqueList extends AbstractTestList {
assertEquals("Duplicate element was added", 2, lset.size());
}
public void testUniqueListReInsert() {
List l = SetUniqueList.decorate(new LinkedList());
l.add(new Object());
l.add(new Object());
Object a = l.get(0);
// duplicate is removed
l.set(0, l.get(1));
assertEquals(1, l.size());
// old object is added back in
l.add(1, a);
assertEquals(2, l.size());
}
public void testUniqueListDoubleInsert() {
List l = SetUniqueList.decorate(new LinkedList());
l.add(new Object());
l.add(new Object());
// duplicate is removed
l.set(0, l.get(1));
assertEquals(1, l.size());
// duplicate should be removed again
l.add(1, l.get(0));
assertEquals(1, l.size());
}
public void testSetDownwardsInList() {
/*
* Checks the following semantics
* [a,b]
* set(0,b): [b]->a
* So UniqList contains [b] and a is returned
*/
ArrayList l = new ArrayList();
HashSet s = new HashSet();
final SetUniqueList ul = new SetUniqueList(l, s);
Object a = new Object();
Object b = new Object();
ul.add(a);
ul.add(b);
assertEquals(a, l.get(0));
assertEquals(b, l.get(1));
assertTrue(s.contains(a));
assertTrue(s.contains(b));
assertEquals(a, ul.set(0, b));
assertEquals(1, s.size());
assertEquals(1, l.size());
assertEquals(b, l.get(0));
assertTrue(s.contains(b));
assertFalse(s.contains(a));
}
public void testSetInBiggerList() {
/*
* Checks the following semantics
* [a,b,c]
* set(0,b): [b,c]->a
* So UniqList contains [b,c] and a is returned
*/
ArrayList l = new ArrayList();
HashSet s = new HashSet();
final SetUniqueList ul = new SetUniqueList(l, s);
Object a = new Object();
Object b = new Object();
Object c = new Object();
ul.add(a);
ul.add(b);
ul.add(c);
assertEquals(a, l.get(0));
assertEquals(b, l.get(1));
assertEquals(c, l.get(2));
assertTrue(s.contains(a));
assertTrue(s.contains(b));
assertTrue(s.contains(c));
assertEquals(a, ul.set(0, b));
assertEquals(2, s.size());
assertEquals(2, l.size());
assertEquals(b, l.get(0));
assertEquals(c, l.get(1));
assertFalse(s.contains(a));
assertTrue(s.contains(b));
assertTrue(s.contains(c));
}
public void testSetUpwardsInList() {
/*
* Checks the following semantics
* [a,b,c]
* set(1,a): [a,c]->b
* So UniqList contains [a,c] and b is returned
*/
ArrayList l = new ArrayList();
HashSet s = new HashSet();
final SetUniqueList ul = new SetUniqueList(l, s);
Object a = new String("A");
Object b = new String("B");
Object c = new String("C");
ul.add(a);
ul.add(b);
ul.add(c);
assertEquals(a, l.get(0));
assertEquals(b, l.get(1));
assertEquals(c, l.get(2));
assertTrue(s.contains(a));
assertTrue(s.contains(b));
assertTrue(s.contains(c));
assertEquals(b, ul.set(1, a));
assertEquals(2, s.size());
assertEquals(2, l.size());
assertEquals(a, l.get(0));
assertEquals(c, l.get(1));
assertTrue(s.contains(a));
assertFalse(s.contains(b));
assertTrue(s.contains(c));
}
//-----------------------------------------------------------------------
public String getCompatibilityVersion() {
return "3.1";
}