From 81af3aaa9a03e503e29799b9c3de9f3ddb3e875b Mon Sep 17 00:00:00 2001 From: Thomas Neidhart Date: Sun, 8 Nov 2015 21:12:28 +0000 Subject: [PATCH] Backport COLLECTIONS-307 to 3.2.2. git-svn-id: https://svn.apache.org/repos/asf/commons/proper/collections/branches/COLLECTIONS_3_2_X@1713295 13f79535-47bb-0310-9956-ffa450edef68 --- src/changes/changes.xml | 8 ++-- .../collections/list/SetUniqueList.java | 30 ++++++++++++++- .../collections/list/TestSetUniqueList.java | 38 +++++++++++++++++++ 3 files changed, 71 insertions(+), 5 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 053ccc5b4..a415a91bf 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -38,6 +38,10 @@ Synchronized access to lock in "StaticBucketMap#size()". + + "SetUniqueList#subList()#contains(Object)" will now correctly check the subList + rather than the parent list. + "CaseInsensitiveMap" will now convert input strings to lower-case in a locale-independent manner. @@ -82,10 +86,6 @@ "LRUMap#keySet()#remove(Object)" will not throw a "ConcurrentModificationException" anymore. - - "SetUniqueList#subList()#contains(Object)" will now correctly check the subList - rather than the parent list. - "SetUniqueList#set(int, Object)" will now correctly enforce the uniqueness constraint. diff --git a/src/java/org/apache/commons/collections/list/SetUniqueList.java b/src/java/org/apache/commons/collections/list/SetUniqueList.java index 3eb5f344c..c9f014893 100644 --- a/src/java/org/apache/commons/collections/list/SetUniqueList.java +++ b/src/java/org/apache/commons/collections/list/SetUniqueList.java @@ -277,7 +277,35 @@ public class SetUniqueList extends AbstractSerializableListDecorator { } public List subList(int fromIndex, int toIndex) { - return new SetUniqueList(super.subList(fromIndex, toIndex), set); + List superSubList = super.subList(fromIndex, toIndex); + Set subSet = createSetBasedOnList(set, superSubList); + return new SetUniqueList(superSubList, subSet); + } + + /** + * Create a new {@link Set} with the same type as the provided {@code set} + * and populate it with all elements of {@code list}. + * + * @param set the {@link Set} to be used as return type, must not be null + * @param list the {@link List} to populate the {@link Set} + * @return a new {@link Set} populated with all elements of the provided + * {@link List} + */ + protected Set createSetBasedOnList(Set set, List list) { + Set subSet = null; + if(set.getClass().equals(HashSet.class)) { + subSet = new HashSet(); + } else { + try { + subSet = (Set) set.getClass().newInstance(); + } catch(InstantiationException ie) { + subSet = new HashSet(); + } catch(IllegalAccessException iae) { + subSet = new HashSet(); + } + } + subSet.addAll(list); + return subSet; } //----------------------------------------------------------------------- diff --git a/src/test/org/apache/commons/collections/list/TestSetUniqueList.java b/src/test/org/apache/commons/collections/list/TestSetUniqueList.java index fe08150e9..519cd5966 100644 --- a/src/test/org/apache/commons/collections/list/TestSetUniqueList.java +++ b/src/test/org/apache/commons/collections/list/TestSetUniqueList.java @@ -22,6 +22,7 @@ import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; +import java.util.Set; import junit.framework.Test; import junit.framework.TestSuite; @@ -430,6 +431,43 @@ public class TestSetUniqueList extends AbstractTestList { assertTrue(s.contains(c)); } + public void testCollections307() { + List list = new ArrayList(); + List uniqueList = SetUniqueList.decorate(list); + String hello = "Hello"; + String world = "World"; + uniqueList.add(hello); + uniqueList.add(world); + List subList = list.subList(0, 0); + List subUniqueList = uniqueList.subList(0, 0); + assertFalse(subList.contains(world)); // passes + assertFalse(subUniqueList.contains(world)); // fails + List worldList = new ArrayList(); + worldList.add(world); + assertFalse(subList.contains("World")); // passes + assertFalse(subUniqueList.contains("World")); // fails + // repeat the test with a different class than HashSet; + // which means subclassing SetUniqueList below + list = new ArrayList(); + uniqueList = new SetUniqueList307(list, new java.util.TreeSet()); + uniqueList.add(hello); + uniqueList.add(world); + subList = list.subList(0, 0); + subUniqueList = uniqueList.subList(0, 0); + assertFalse(subList.contains(world)); // passes + assertFalse(subUniqueList.contains(world)); // fails + worldList = new ArrayList(); + worldList.add(world); + assertFalse(subList.contains("World")); // passes + assertFalse(subUniqueList.contains("World")); // fails + } + + class SetUniqueList307 extends SetUniqueList { + public SetUniqueList307(List list, Set set) { + super(list, set); + } + } + //----------------------------------------------------------------------- public String getCompatibilityVersion() { return "3.1";