View | Details | Raw Unified | Return to bug 58740
Collapse All | Expand All

(-)src/main/java/org/apache/commons/collections4/list/MapUniqueList.java (-73 / +97 lines)
Lines 18-27 Link Here
18
18
19
import java.util.ArrayList;
19
import java.util.ArrayList;
20
import java.util.Collection;
20
import java.util.Collection;
21
import java.util.HashSet;
21
import java.util.HashMap;
22
import java.util.Iterator;
22
import java.util.Iterator;
23
import java.util.List;
23
import java.util.List;
24
import java.util.ListIterator;
24
import java.util.ListIterator;
25
import java.util.Map;
25
import java.util.Set;
26
import java.util.Set;
26
27
27
import org.apache.commons.collections4.ListUtils;
28
import org.apache.commons.collections4.ListUtils;
Lines 31-46 Link Here
31
32
32
/**
33
/**
33
 * Decorates a <code>List</code> to ensure that no duplicates are present much
34
 * Decorates a <code>List</code> to ensure that no duplicates are present much
34
 * like a <code>Set</code>.
35
 * like a <code>Map</code>.
35
 * <p>
36
 * <p>
36
 * The <code>List</code> interface makes certain assumptions/requirements. This
37
 * The <code>List</code> interface makes certain assumptions/requirements. This
37
 * implementation breaks these in certain ways, but this is merely the result of
38
 * implementation breaks these in certain ways, but this is merely the result of
38
 * rejecting duplicates. Each violation is explained in the method, but it
39
 * rejecting duplicates. Each violation is explained in the method, but it
39
 * should not affect you. Bear in mind that Sets require immutable objects to
40
 * should not affect you. Bear in mind that Maps require immutable objects to
40
 * function correctly.
41
 * function correctly.
41
 * <p>
42
 * <p>
42
 * The {@link org.apache.commons.collections4.set.ListOrderedSet ListOrderedSet}
43
 * The {@link org.apache.commons.collections4.set.ListOrderedMap ListOrderedMap}
43
 * class provides an alternative approach, by wrapping an existing Set and
44
 * class provides an alternative approach, by wrapping an existing Map and
44
 * retaining insertion order in the iterator.
45
 * retaining insertion order in the iterator.
45
 * <p>
46
 * <p>
46
 * This class is Serializable from Commons Collections 3.1.
47
 * This class is Serializable from Commons Collections 3.1.
Lines 48-103 Link Here
48
 * @since 3.0
49
 * @since 3.0
49
 * @version $Id$
50
 * @version $Id$
50
 */
51
 */
51
public class SetUniqueList<E> extends AbstractSerializableListDecorator<E> {
52
public class MapUniqueList<E> extends AbstractSerializableListDecorator<E> {
52
53
53
    /** Serialization version. */
54
    /** Serialization version. */
54
    private static final long serialVersionUID = 7196982186153478694L;
55
    private static final long serialVersionUID = 5539814519665417789L;
55
56
56
    /** Internal Set to maintain uniqueness. */
57
    /** Internal Map to maintain uniqueness. */
57
    private final Set<E> set;
58
    private final Map<E, Integer> map;
58
59
59
    /**
60
    /**
60
     * Factory method to create a SetList using the supplied list to retain order.
61
     * Factory method to create a MapList using the supplied list to retain order.
61
     * <p>
62
     * <p>
62
     * If the list contains duplicates, these are removed (first indexed one
63
     * If the list contains duplicates, these are removed (first indexed one
63
     * kept). A <code>HashSet</code> is used for the set behaviour.
64
     * kept). A <code>HashMap</code> is used for the set behaviour. The map
65
     * also gives better performance for indexOf, contains(E), and get(E).
64
     *
66
     *
65
     * @param <E>  the element type
67
     * @param <E>  the element type
66
     * @param list  the list to decorate, must not be null
68
     * @param list  the list to decorate, must not be null
67
     * @return a new {@link SetUniqueList}
69
     * @return a new {@link MapUniqueList}
68
     * @throws NullPointerException if list is null
70
     * @throws NullPointerException if list is null
69
     * @since 4.0
71
     * @since FIXME
70
     */
72
     */
71
    public static <E> SetUniqueList<E> setUniqueList(final List<E> list) {
73
    public static <E> MapUniqueList<E> mapUniqueList(final List<E> list) {
72
        if (list == null) {
74
        if (list == null) {
73
            throw new NullPointerException("List must not be null");
75
            throw new NullPointerException("List must not be null");
74
        }
76
        }
77
        final Map<E, Integer> map = new HashMap<E, Integer>();
75
        if (list.isEmpty()) {
78
        if (list.isEmpty()) {
76
            return new SetUniqueList<E>(list, new HashSet<E>());
79
            return new MapUniqueList<E>(list, map);
77
        }
80
        }
78
        final List<E> temp = new ArrayList<E>(list);
81
        final List<E> temp = new ArrayList<E>(list);
79
        list.clear();
82
        list.clear();
80
        final SetUniqueList<E> sl = new SetUniqueList<E>(list, new HashSet<E>());
83
        final MapUniqueList<E> maplist = new MapUniqueList<E>(list, map);
81
        sl.addAll(temp);
84
        maplist.addAll(temp);
82
        return sl;
85
        return maplist;
83
    }
86
    }
84
87
85
    // -----------------------------------------------------------------------
88
    // -----------------------------------------------------------------------
86
    /**
89
    /**
87
     * Constructor that wraps (not copies) the List and specifies the set to use.
90
     * Constructor that wraps (not copies) the List and specifies the map to use.
88
     * <p>
91
     * <p>
89
     * The set and list must both be correctly initialised to the same elements.
92
     * The map and list must both be correctly initialised to the same elements.
90
     *
93
     *
91
     * @param set  the set to decorate, must not be null
94
     * @param map  the map to decorate, must not be null
92
     * @param list  the list to decorate, must not be null
95
     * @param list  the list to decorate, must not be null
93
     * @throws NullPointerException if set or list is null
96
     * @throws NullPointerException if map or list is null
94
     */
97
     */
95
    protected SetUniqueList(final List<E> list, final Set<E> set) {
98
    protected MapUniqueList(final List<E> list, final Map<E, Integer> map) {
96
        super(list);
99
        super(list);
97
        if (set == null) {
100
        if (map == null) {
98
            throw new NullPointerException("Set must not be null");
101
            throw new NullPointerException("Map must not be null");
99
        }
102
        }
100
        this.set = set;
103
        this.map = map;
101
    }
104
    }
102
105
103
    // -----------------------------------------------------------------------
106
    // -----------------------------------------------------------------------
Lines 107-113 Link Here
107
     * @return an unmodifiable set view
110
     * @return an unmodifiable set view
108
     */
111
     */
109
    public Set<E> asSet() {
112
    public Set<E> asSet() {
110
        return UnmodifiableSet.unmodifiableSet(set);
113
        return UnmodifiableSet.unmodifiableSet(map.keySet());
111
    }
114
    }
112
115
113
    // -----------------------------------------------------------------------
116
    // -----------------------------------------------------------------------
Lines 116-122 Link Here
116
     * <p>
119
     * <p>
117
     * <i>(Violation)</i> The <code>List</code> interface requires that this
120
     * <i>(Violation)</i> The <code>List</code> interface requires that this
118
     * method returns <code>true</code> always. However this class may return
121
     * method returns <code>true</code> always. However this class may return
119
     * <code>false</code> because of the <code>Set</code> behaviour.
122
     * <code>false</code> because of the uniqueness criteria.
120
     *
123
     *
121
     * @param object  the object to add
124
     * @param object  the object to add
122
     * @return true if object was added
125
     * @return true if object was added
Lines 147-155 Link Here
147
    @Override
150
    @Override
148
    public void add(final int index, final E object) {
151
    public void add(final int index, final E object) {
149
        // adds element if it is not contained already
152
        // adds element if it is not contained already
150
        if (set.contains(object) == false) {
153
        if (map.containsKey(object) == false) {
151
            super.add(index, object);
154
            super.add(index, object);
152
            set.add(object);
155
            map.put(object, index);
153
        }
156
        }
154
    }
157
    }
155
158
Lines 168-174 Link Here
168
     */
171
     */
169
    @Override
172
    @Override
170
    public boolean addAll(final Collection<? extends E> coll) {
173
    public boolean addAll(final Collection<? extends E> coll) {
171
        return addAll(size(), coll);
174
        //return addAll(size(), coll);
175
        boolean changed = false;
176
        for (E e : coll) {
177
            changed |= add(e);
178
        }
179
        return changed;
172
    }
180
    }
173
181
174
    /**
182
    /**
Lines 188-200 Link Here
188
     */
196
     */
189
    @Override
197
    @Override
190
    public boolean addAll(final int index, final Collection<? extends E> coll) {
198
    public boolean addAll(final int index, final Collection<? extends E> coll) {
191
        final List<E> temp = new ArrayList<E>();
199
        /*final List<E> temp = new ArrayList<E>();
192
        for (final E e : coll) {
200
        for (final E e : coll) {
193
            if (set.add(e)) {
201
            if (map.add(e)) {
194
                temp.add(e);
202
                temp.add(e);
195
            }
203
            }
196
        }
204
        }
197
        return super.addAll(index, temp);
205
        return super.addAll(index, temp);*/
206
        boolean changed = false;
207
        int i = index;
208
        for (E e : coll) {
209
            if (!map.containsKey(e)) {
210
                add(i, e);
211
                i++;
212
                changed = true;
213
            }
214
        }
215
        return changed;
198
    }
216
    }
199
217
200
    // -----------------------------------------------------------------------
218
    // -----------------------------------------------------------------------
Lines 220-234 Link Here
220
            super.remove(pos); // remove the duplicate by index
238
            super.remove(pos); // remove the duplicate by index
221
        }
239
        }
222
240
223
        set.remove(removed); // remove the item deleted by the set
241
        map.remove(removed); // remove the item deleted by the map
224
        set.add(object); // add the new item to the unique set
242
        map.put(object, index); // add the new item to the unique map
225
243
226
        return removed; // return the item deleted by the set
244
        return removed; // return the item deleted by the map
227
    }
245
    }
228
246
229
    @Override
247
    @Override
230
    public boolean remove(final Object object) {
248
    public boolean remove(final Object object) {
231
        final boolean result = set.remove(object);
249
        final boolean result = map.remove(object) != null;
232
        if (result) {
250
        if (result) {
233
            super.remove(object);
251
            super.remove(object);
234
        }
252
        }
Lines 238-244 Link Here
238
    @Override
256
    @Override
239
    public E remove(final int index) {
257
    public E remove(final int index) {
240
        final E result = super.remove(index);
258
        final E result = super.remove(index);
241
        set.remove(result);
259
        map.remove(result);
242
        return result;
260
        return result;
243
    }
261
    }
244
262
Lines 262-267 Link Here
262
     */
280
     */
263
    @Override
281
    @Override
264
    public boolean retainAll(final Collection<?> coll) {
282
    public boolean retainAll(final Collection<?> coll) {
283
        final Set<E> set = map.keySet();
265
        boolean result = set.retainAll(coll);
284
        boolean result = set.retainAll(coll);
266
        if (result == false) {
285
        if (result == false) {
267
            return false;
286
            return false;
Lines 269-275 Link Here
269
        if (set.size() == 0) {
288
        if (set.size() == 0) {
270
            super.clear();
289
            super.clear();
271
        } else {
290
        } else {
272
            // use the set as parameter for the call to retainAll to improve performance
291
            // use the map as parameter for the call to retainAll to improve performance
273
            super.retainAll(set);
292
            super.retainAll(set);
274
        }
293
        }
275
        return result;
294
        return result;
Lines 278-309 Link Here
278
    @Override
297
    @Override
279
    public void clear() {
298
    public void clear() {
280
        super.clear();
299
        super.clear();
281
        set.clear();
300
        map.clear();
282
    }
301
    }
283
302
284
    @Override
303
    @Override
285
    public boolean contains(final Object object) {
304
    public boolean contains(final Object object) {
286
        return set.contains(object);
305
        return map.containsKey(object);
287
    }
306
    }
288
307
289
    @Override
308
    @Override
290
    public boolean containsAll(final Collection<?> coll) {
309
    public boolean containsAll(final Collection<?> coll) {
291
        return set.containsAll(coll);
310
        return map.keySet().containsAll(coll);
292
    }
311
    }
293
312
294
    @Override
313
    @Override
295
    public Iterator<E> iterator() {
314
    public Iterator<E> iterator() {
296
        return new SetListIterator<E>(super.iterator(), set);
315
        return new MapListIterator<E>(super.iterator(), map);
297
    }
316
    }
298
317
299
    @Override
318
    @Override
300
    public ListIterator<E> listIterator() {
319
    public ListIterator<E> listIterator() {
301
        return new SetListListIterator<E>(super.listIterator(), set);
320
        return new MapListListIterator<E>(super.listIterator(), map);
302
    }
321
    }
303
322
304
    @Override
323
    @Override
305
    public ListIterator<E> listIterator(final int index) {
324
    public ListIterator<E> listIterator(final int index) {
306
        return new SetListListIterator<E>(super.listIterator(index), set);
325
        return new MapListListIterator<E>(super.listIterator(index), map);
307
    }
326
    }
308
327
309
    /**
328
    /**
Lines 315-349 Link Here
315
    @Override
334
    @Override
316
    public List<E> subList(final int fromIndex, final int toIndex) {
335
    public List<E> subList(final int fromIndex, final int toIndex) {
317
        final List<E> superSubList = super.subList(fromIndex, toIndex);
336
        final List<E> superSubList = super.subList(fromIndex, toIndex);
318
        final Set<E> subSet = createSetBasedOnList(set, superSubList);
337
        final Map<E, Integer> subMap = createMapBasedOnList(map, superSubList);
319
        return ListUtils.unmodifiableList(new SetUniqueList<E>(superSubList, subSet));
338
        return ListUtils.unmodifiableList(new MapUniqueList<E>(superSubList, subMap));
320
    }
339
    }
321
340
322
    /**
341
    /**
323
     * Create a new {@link Set} with the same type as the provided {@code set}
342
     * Create a new {@link Map} with the same type as the provided {@code map}
324
     * and populate it with all elements of {@code list}.
343
     * and populate it with all elements of {@code list}.
325
     *
344
     *
326
     * @param set  the {@link Set} to be used as return type, must not be null
345
     * @param map  the {@link Map} to be used as return type, must not be null
327
     * @param list  the {@link List} to populate the {@link Set}
346
     * @param list  the {@link List} to populate the {@link Map}
328
     * @return a new {@link Set} populated with all elements of the provided
347
     * @return a new {@link Map} populated with all elements of the provided
329
     *   {@link List}
348
     *   {@link List}
330
     */
349
     */
331
    @SuppressWarnings("unchecked")
350
    @SuppressWarnings("unchecked")
332
    protected Set<E> createSetBasedOnList(final Set<E> set, final List<E> list) {
351
    protected Map<E, Integer> createMapBasedOnList(final Map<E, Integer> map, final List<E> list) {
333
        Set<E> subSet;
352
        Map<E, Integer> subMap;
334
        if (set.getClass().equals(HashSet.class)) {
353
        if (map.getClass().equals(HashMap.class)) {
335
            subSet = new HashSet<E>(list.size());
354
            subMap = new HashMap<E, Integer>(list.size());
336
        } else {
355
        } else {
337
            try {
356
            try {
338
                subSet = set.getClass().newInstance();
357
                subMap = map.getClass().newInstance();
339
            } catch (final InstantiationException ie) {
358
            } catch (final InstantiationException ie) {
340
                subSet = new HashSet<E>();
359
                subMap = new HashMap<E, Integer>();
341
            } catch (final IllegalAccessException iae) {
360
            } catch (final IllegalAccessException iae) {
342
                subSet = new HashSet<E>();
361
                subMap = new HashMap<E, Integer>();
343
            }
362
            }
344
        }
363
        }
345
        subSet.addAll(list);
364
        assert subMap.isEmpty();
346
        return subSet;
365
        for (E e : list) {
366
            if (! subMap.containsKey(e)) {
367
                subMap.put(e, subMap.size());
368
            }
369
        }
370
        return subMap;
347
    }
371
    }
348
372
349
    // -----------------------------------------------------------------------
373
    // -----------------------------------------------------------------------
Lines 350-363 Link Here
350
    /**
374
    /**
351
     * Inner class iterator.
375
     * Inner class iterator.
352
     */
376
     */
353
    static class SetListIterator<E> extends AbstractIteratorDecorator<E> {
377
    static class MapListIterator<E> extends AbstractIteratorDecorator<E> {
354
378
355
        private final Set<E> set;
379
        private final Map<E, Integer> map;
356
        private E last = null;
380
        private E last = null;
357
381
358
        protected SetListIterator(final Iterator<E> it, final Set<E> set) {
382
        protected MapListIterator(final Iterator<E> it, final Map<E, Integer> map) {
359
            super(it);
383
            super(it);
360
            this.set = set;
384
            this.map = map;
361
        }
385
        }
362
386
363
        @Override
387
        @Override
Lines 369-375 Link Here
369
        @Override
393
        @Override
370
        public void remove() {
394
        public void remove() {
371
            super.remove();
395
            super.remove();
372
            set.remove(last);
396
            map.remove(last);
373
            last = null;
397
            last = null;
374
        }
398
        }
375
    }
399
    }
Lines 377-391 Link Here
377
    /**
401
    /**
378
     * Inner class iterator.
402
     * Inner class iterator.
379
     */
403
     */
380
    static class SetListListIterator<E> extends
404
    static class MapListListIterator<E> extends
381
            AbstractListIteratorDecorator<E> {
405
            AbstractListIteratorDecorator<E> {
382
406
383
        private final Set<E> set;
407
        private final Map<E, Integer> map;
384
        private E last = null;
408
        private E last = null;
385
409
386
        protected SetListListIterator(final ListIterator<E> it, final Set<E> set) {
410
        protected MapListListIterator(final ListIterator<E> it, final Map<E, Integer> map) {
387
            super(it);
411
            super(it);
388
            this.set = set;
412
            this.map = map;
389
        }
413
        }
390
414
391
        @Override
415
        @Override
Lines 403-417 Link Here
403
        @Override
427
        @Override
404
        public void remove() {
428
        public void remove() {
405
            super.remove();
429
            super.remove();
406
            set.remove(last);
430
            map.remove(last);
407
            last = null;
431
            last = null;
408
        }
432
        }
409
433
410
        @Override
434
        @Override
411
        public void add(final E object) {
435
        public void add(final E object) {
412
            if (set.contains(object) == false) {
436
            if (map.containsKey(object) == false) {
413
                super.add(object);
437
                super.add(object);
414
                set.add(object);
438
                map.put(object, map.size());
415
            }
439
            }
416
        }
440
        }
417
441
(-)src/test/java/org/apache/commons/collections4/list/MapUniqueListTest.java (-116 / +120 lines)
Lines 19-39 Link Here
19
import java.util.ArrayList;
19
import java.util.ArrayList;
20
import java.util.Arrays;
20
import java.util.Arrays;
21
import java.util.Collection;
21
import java.util.Collection;
22
import java.util.HashSet;
22
import java.util.HashMap;
23
import java.util.LinkedList;
23
import java.util.LinkedList;
24
import java.util.List;
24
import java.util.List;
25
import java.util.ListIterator;
25
import java.util.ListIterator;
26
import java.util.Set;
26
import java.util.Map;
27
27
28
/**
28
/**
29
 * JUnit tests.
29
 * JUnit tests.
30
 *
30
 *
31
 * @since 3.0
31
 * @since FIXME
32
 * @version $Id$
32
 * @version $Id$
33
 */
33
 */
34
public class SetUniqueListTest<E> extends AbstractListTest<E> {
34
public class MapUniqueListTest<E> extends AbstractListTest<E> {
35
35
36
    public SetUniqueListTest(final String testName) {
36
    public MapUniqueListTest(final String testName) {
37
        super(testName);
37
        super(testName);
38
    }
38
    }
39
39
Lines 40-46 Link Here
40
    //-----------------------------------------------------------------------
40
    //-----------------------------------------------------------------------
41
    @Override
41
    @Override
42
    public List<E> makeObject() {
42
    public List<E> makeObject() {
43
        return new SetUniqueList<E>(new ArrayList<E>(), new HashSet<E>());
43
        return new MapUniqueList<E>(new ArrayList<E>(), new HashMap<E, Integer>());
44
    }
44
    }
45
45
46
    //-----------------------------------------------------------------------
46
    //-----------------------------------------------------------------------
Lines 83-89 Link Here
83
83
84
    @Override
84
    @Override
85
    public void testListIteratorAdd() {
85
    public void testListIteratorAdd() {
86
        // override to cope with Set behaviour
86
        // override to cope with Map behaviour
87
        resetEmpty();
87
        resetEmpty();
88
        final List<E> list1 = getCollection();
88
        final List<E> list1 = getCollection();
89
        final List<E> list2 = getConfirmed();
89
        final List<E> list2 = getConfirmed();
Lines 112-118 Link Here
112
112
113
    @Override
113
    @Override
114
    public void testCollectionAddAll() {
114
    public void testCollectionAddAll() {
115
        // override for set behaviour
115
        // override for map behaviour
116
        resetEmpty();
116
        resetEmpty();
117
        E[] elements = getFullElements();
117
        E[] elements = getFullElements();
118
        boolean r = getCollection().addAll(Arrays.asList(elements));
118
        boolean r = getCollection().addAll(Arrays.asList(elements));
Lines 140-147 Link Here
140
    }
140
    }
141
141
142
    public void testIntCollectionAddAll() {
142
    public void testIntCollectionAddAll() {
143
      // make a SetUniqueList with one element
143
      // make a MapUniqueList with one element
144
      final List<Integer> list = new SetUniqueList<Integer>(new ArrayList<Integer>(), new HashSet<Integer>());
144
      final List<Integer> alist = new ArrayList<Integer>();
145
      final Map<Integer, Integer> map = new HashMap<Integer, Integer>();
146
      final List<Integer> list = new MapUniqueList<Integer>(alist, map);
145
      final Integer existingElement = Integer.valueOf(1);
147
      final Integer existingElement = Integer.valueOf(1);
146
      list.add(existingElement);
148
      list.add(existingElement);
147
149
Lines 167-173 Link Here
167
    @Override
169
    @Override
168
    @SuppressWarnings("unchecked")
170
    @SuppressWarnings("unchecked")
169
    public void testListSetByIndex() {
171
    public void testListSetByIndex() {
170
        // override for set behaviour
172
        // override for map behaviour
171
        resetFull();
173
        resetFull();
172
        final int size = getCollection().size();
174
        final int size = getCollection().size();
173
        getCollection().set(0, (E) new Long(1000));
175
        getCollection().set(0, (E) new Long(1000));
Lines 175-181 Link Here
175
177
176
        getCollection().set(2, (E) new Long(1000));
178
        getCollection().set(2, (E) new Long(1000));
177
        assertEquals(size - 1, getCollection().size());
179
        assertEquals(size - 1, getCollection().size());
178
        assertEquals(new Long(1000), getCollection().get(1));  // set into 2, but shifted down to 1
180
        assertEquals(new Long(1000), getCollection().get(1));  // map into 2, but shifted down to 1
179
    }
181
    }
180
182
181
    boolean extraVerify = true;
183
    boolean extraVerify = true;
Lines 211-221 Link Here
211
    public void testFactory() {
213
    public void testFactory() {
212
        final Integer[] array = new Integer[] { Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(1) };
214
        final Integer[] array = new Integer[] { Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(1) };
213
        final ArrayList<Integer> list = new ArrayList<Integer>(Arrays.asList(array));
215
        final ArrayList<Integer> list = new ArrayList<Integer>(Arrays.asList(array));
214
        final SetUniqueList<Integer> lset = SetUniqueList.setUniqueList(list);
216
        final MapUniqueList<Integer> lmap = MapUniqueList.mapUniqueList(list);
215
217
216
        assertEquals("Duplicate element was added.", 2, lset.size());
218
        assertEquals("Duplicate element was added.", 2, lmap.size());
217
        assertEquals(Integer.valueOf(1), lset.get(0));
219
        assertEquals(Integer.valueOf(1), lmap.get(0));
218
        assertEquals(Integer.valueOf(2), lset.get(1));
220
        assertEquals(Integer.valueOf(2), lmap.get(1));
219
        assertEquals(Integer.valueOf(1), list.get(0));
221
        assertEquals(Integer.valueOf(1), list.get(0));
220
        assertEquals(Integer.valueOf(2), list.get(1));
222
        assertEquals(Integer.valueOf(2), list.get(1));
221
    }
223
    }
Lines 222-253 Link Here
222
224
223
    @SuppressWarnings("unchecked")
225
    @SuppressWarnings("unchecked")
224
    public void testAdd() {
226
    public void testAdd() {
225
        final SetUniqueList<E> lset = new SetUniqueList<E>(new ArrayList<E>(), new HashSet<E>());
227
        final MapUniqueList<E> lmap = new MapUniqueList<E>(new ArrayList<E>(), new HashMap<E, Integer>());
226
228
227
        // Duplicate element
229
        // Duplicate element
228
        final E obj = (E) Integer.valueOf(1);
230
        final E obj = (E) Integer.valueOf(1);
229
        lset.add(obj);
231
        lmap.add(obj);
230
        lset.add(obj);
232
        lmap.add(obj);
231
        assertEquals("Duplicate element was added.", 1, lset.size());
233
        assertEquals("Duplicate element was added.", 1, lmap.size());
232
234
233
        // Unique element
235
        // Unique element
234
        lset.add((E) Integer.valueOf(2));
236
        lmap.add((E) Integer.valueOf(2));
235
        assertEquals("Unique element was not added.", 2, lset.size());
237
        assertEquals("Unique element was not added.", 2, lmap.size());
236
    }
238
    }
237
239
238
    @SuppressWarnings("unchecked")
240
    @SuppressWarnings("unchecked")
239
    public void testAddAll() {
241
    public void testAddAll() {
240
        final SetUniqueList<E> lset = new SetUniqueList<E>(new ArrayList<E>(), new HashSet<E>());
242
        final MapUniqueList<E> lmap = new MapUniqueList<E>(new ArrayList<E>(), new HashMap<E, Integer>());
241
243
242
        lset.addAll(
244
        lmap.addAll(
243
            Arrays.asList((E[]) new Integer[] { Integer.valueOf(1), Integer.valueOf(1)}));
245
            Arrays.asList((E[]) new Integer[] { Integer.valueOf(1), Integer.valueOf(1)}));
244
246
245
        assertEquals("Duplicate element was added.", 1, lset.size());
247
        assertEquals("Duplicate element was added.", 1, lmap.size());
246
    }
248
    }
247
249
248
    @SuppressWarnings("unchecked")
250
    @SuppressWarnings("unchecked")
249
    public void testSet() {
251
    public void testMap() {
250
        final SetUniqueList<E> lset = new SetUniqueList<E>(new ArrayList<E>(), new HashSet<E>());
252
        final MapUniqueList<E> lmap = new MapUniqueList<E>(new ArrayList<E>(), new HashMap<E, Integer>());
251
253
252
        // Duplicate element
254
        // Duplicate element
253
        final E obj1 = (E) Integer.valueOf(1);
255
        final E obj1 = (E) Integer.valueOf(1);
Lines 254-300 Link Here
254
        final E obj2 = (E) Integer.valueOf(2);
256
        final E obj2 = (E) Integer.valueOf(2);
255
        final E obj3 = (E) Integer.valueOf(3);
257
        final E obj3 = (E) Integer.valueOf(3);
256
258
257
        lset.add(obj1);
259
        lmap.add(obj1);
258
        lset.add(obj2);
260
        lmap.add(obj2);
259
        lset.set(0, obj1);
261
        lmap.set(0, obj1);
260
        assertEquals(2, lset.size());
262
        assertEquals(2, lmap.size());
261
        assertSame(obj1, lset.get(0));
263
        assertSame(obj1, lmap.get(0));
262
        assertSame(obj2, lset.get(1));
264
        assertSame(obj2, lmap.get(1));
263
265
264
        lset.clear();
266
        lmap.clear();
265
        lset.add(obj1);
267
        lmap.add(obj1);
266
        lset.add(obj2);
268
        lmap.add(obj2);
267
        lset.set(0, obj2);
269
        lmap.set(0, obj2);
268
        assertEquals(1, lset.size());
270
        assertEquals(1, lmap.size());
269
        assertSame(obj2, lset.get(0));
271
        assertSame(obj2, lmap.get(0));
270
272
271
        lset.clear();
273
        lmap.clear();
272
        lset.add(obj1);
274
        lmap.add(obj1);
273
        lset.add(obj2);
275
        lmap.add(obj2);
274
        lset.set(0, obj3);
276
        lmap.set(0, obj3);
275
        assertEquals(2, lset.size());
277
        assertEquals(2, lmap.size());
276
        assertSame(obj3, lset.get(0));
278
        assertSame(obj3, lmap.get(0));
277
        assertSame(obj2, lset.get(1));
279
        assertSame(obj2, lmap.get(1));
278
280
279
        lset.clear();
281
        lmap.clear();
280
        lset.add(obj1);
282
        lmap.add(obj1);
281
        lset.add(obj2);
283
        lmap.add(obj2);
282
        lset.set(1, obj1);
284
        lmap.set(1, obj1);
283
        assertEquals(1, lset.size());
285
        assertEquals(1, lmap.size());
284
        assertSame(obj1, lset.get(0));
286
        assertSame(obj1, lmap.get(0));
285
    }
287
    }
286
288
287
    @SuppressWarnings("unchecked")
289
    @SuppressWarnings("unchecked")
288
    public void testListIterator() {
290
    public void testListIterator() {
289
        final SetUniqueList<E> lset = new SetUniqueList<E>(new ArrayList<E>(), new HashSet<E>());
291
        final MapUniqueList<E> lmap = new MapUniqueList<E>(new ArrayList<E>(), new HashMap<E, Integer>());
290
292
291
        final E obj1 = (E) Integer.valueOf(1);
293
        final E obj1 = (E) Integer.valueOf(1);
292
        final E obj2 = (E) Integer.valueOf(2);
294
        final E obj2 = (E) Integer.valueOf(2);
293
        lset.add(obj1);
295
        lmap.add(obj1);
294
        lset.add(obj2);
296
        lmap.add(obj2);
295
297
296
        // Attempts to add a duplicate object
298
        // Attempts to add a duplicate object
297
        for (final ListIterator<E> it = lset.listIterator(); it.hasNext();) {
299
        for (final ListIterator<E> it = lmap.listIterator(); it.hasNext();) {
298
            it.next();
300
            it.next();
299
301
300
            if (!it.hasNext()) {
302
            if (!it.hasNext()) {
Lines 303-314 Link Here
303
            }
305
            }
304
        }
306
        }
305
307
306
        assertEquals("Duplicate element was added", 2, lset.size());
308
        assertEquals("Duplicate element was added", 2, lmap.size());
307
    }
309
    }
308
310
309
    @SuppressWarnings("unchecked")
311
    @SuppressWarnings("unchecked")
310
    public void testUniqueListReInsert() {
312
    public void testUniqueListReInsert() {
311
        final List<E> l = SetUniqueList.setUniqueList(new LinkedList<E>());
313
        final List<E> l = MapUniqueList.mapUniqueList(new LinkedList<E>());
312
        l.add((E) new Object());
314
        l.add((E) new Object());
313
        l.add((E) new Object());
315
        l.add((E) new Object());
314
316
Lines 325-331 Link Here
325
327
326
    @SuppressWarnings("unchecked")
328
    @SuppressWarnings("unchecked")
327
    public void testUniqueListDoubleInsert() {
329
    public void testUniqueListDoubleInsert() {
328
        final List<E> l = SetUniqueList.setUniqueList(new LinkedList<E>());
330
        final List<E> l = MapUniqueList.mapUniqueList(new LinkedList<E>());
329
        l.add((E) new Object());
331
        l.add((E) new Object());
330
        l.add((E) new Object());
332
        l.add((E) new Object());
331
333
Lines 339-354 Link Here
339
    }
341
    }
340
342
341
    @SuppressWarnings("unchecked")
343
    @SuppressWarnings("unchecked")
342
    public void testSetDownwardsInList() {
344
    public void testMapDownwardsInList() {
343
        /*
345
        /*
344
         * Checks the following semantics
346
         * Checks the following semantics
345
         * [a,b]
347
         * [a,b]
346
         * set(0,b): [b]->a
348
         * map(0,b): [b]->a
347
         * So UniqList contains [b] and a is returned
349
         * So UniqList contains [b] and a is returned
348
         */
350
         */
349
        final ArrayList<E> l = new ArrayList<E>();
351
        final ArrayList<E> l = new ArrayList<E>();
350
        final HashSet<E> s = new HashSet<E>();
352
        final HashMap<E, Integer> m = new HashMap<E, Integer>();
351
        final SetUniqueList<E> ul = new SetUniqueList<E>(l, s);
353
        final MapUniqueList<E> ul = new MapUniqueList<E>(l, m);
352
354
353
        final E a = (E) new Object();
355
        final E a = (E) new Object();
354
        final E b = (E) new Object();
356
        final E b = (E) new Object();
Lines 356-383 Link Here
356
        ul.add(b);
358
        ul.add(b);
357
        assertEquals(a, l.get(0));
359
        assertEquals(a, l.get(0));
358
        assertEquals(b, l.get(1));
360
        assertEquals(b, l.get(1));
359
        assertTrue(s.contains(a));
361
        assertTrue(m.containsKey(a));
360
        assertTrue(s.contains(b));
362
        assertTrue(m.containsKey(b));
361
363
362
        assertEquals(a, ul.set(0, b));
364
        assertEquals(a, ul.set(0, b));
363
        assertEquals(1, s.size());
365
        assertEquals(1, m.size());
364
        assertEquals(1, l.size());
366
        assertEquals(1, l.size());
365
        assertEquals(b, l.get(0));
367
        assertEquals(b, l.get(0));
366
        assertTrue(s.contains(b));
368
        assertTrue(m.containsKey(b));
367
        assertFalse(s.contains(a));
369
        assertFalse(m.containsKey(a));
368
    }
370
    }
369
371
370
    @SuppressWarnings("unchecked")
372
    @SuppressWarnings("unchecked")
371
    public void testSetInBiggerList() {
373
    public void testMapInBiggerList() {
372
        /*
374
        /*
373
         * Checks the following semantics
375
         * Checks the following semantics
374
         * [a,b,c]
376
         * [a,b,c]
375
         * set(0,b): [b,c]->a
377
         * map(0,b): [b,c]->a
376
         * So UniqList contains [b,c] and a is returned
378
         * So UniqList contains [b,c] and a is returned
377
         */
379
         */
378
        final ArrayList<E> l = new ArrayList<E>();
380
        final ArrayList<E> l = new ArrayList<E>();
379
        final HashSet<E> s = new HashSet<E>();
381
        final HashMap<E, Integer> m = new HashMap<E, Integer>();
380
        final SetUniqueList<E> ul = new SetUniqueList<E>(l, s);
382
        final MapUniqueList<E> ul = new MapUniqueList<E>(l, m);
381
383
382
        final E a = (E) new Object();
384
        final E a = (E) new Object();
383
        final E b = (E) new Object();
385
        final E b = (E) new Object();
Lines 389-419 Link Here
389
        assertEquals(a, l.get(0));
391
        assertEquals(a, l.get(0));
390
        assertEquals(b, l.get(1));
392
        assertEquals(b, l.get(1));
391
        assertEquals(c, l.get(2));
393
        assertEquals(c, l.get(2));
392
        assertTrue(s.contains(a));
394
        assertTrue(m.containsKey(a));
393
        assertTrue(s.contains(b));
395
        assertTrue(m.containsKey(b));
394
        assertTrue(s.contains(c));
396
        assertTrue(m.containsKey(c));
395
397
396
        assertEquals(a, ul.set(0, b));
398
        assertEquals(a, ul.set(0, b));
397
        assertEquals(2, s.size());
399
        assertEquals(2, m.size());
398
        assertEquals(2, l.size());
400
        assertEquals(2, l.size());
399
        assertEquals(b, l.get(0));
401
        assertEquals(b, l.get(0));
400
        assertEquals(c, l.get(1));
402
        assertEquals(c, l.get(1));
401
        assertFalse(s.contains(a));
403
        assertFalse(m.containsKey(a));
402
        assertTrue(s.contains(b));
404
        assertTrue(m.containsKey(b));
403
        assertTrue(s.contains(c));
405
        assertTrue(m.containsKey(c));
404
    }
406
    }
405
407
406
    @SuppressWarnings("unchecked")
408
    @SuppressWarnings("unchecked")
407
    public void testSetUpwardsInList() {
409
    public void testMapUpwardsInList() {
408
        /*
410
        /*
409
         * Checks the following semantics
411
         * Checks the following semantics
410
         * [a,b,c]
412
         * [a,b,c]
411
         * set(1,a): [a,c]->b
413
         * map(1,a): [a,c]->b
412
         * So UniqList contains [a,c] and b is returned
414
         * So UniqList contains [a,c] and b is returned
413
         */
415
         */
414
        final ArrayList<E> l = new ArrayList<E>();
416
        final ArrayList<E> l = new ArrayList<E>();
415
        final HashSet<E> s = new HashSet<E>();
417
        final HashMap<E, Integer> s = new HashMap<E, Integer>();
416
        final SetUniqueList<E> ul = new SetUniqueList<E>(l, s);
418
        final MapUniqueList<E> ul = new MapUniqueList<E>(l, s);
417
419
418
        final E a = (E) new String("A");
420
        final E a = (E) new String("A");
419
        final E b = (E) new String("B");
421
        final E b = (E) new String("B");
Lines 425-433 Link Here
425
        assertEquals(a, l.get(0));
427
        assertEquals(a, l.get(0));
426
        assertEquals(b, l.get(1));
428
        assertEquals(b, l.get(1));
427
        assertEquals(c, l.get(2));
429
        assertEquals(c, l.get(2));
428
        assertTrue(s.contains(a));
430
        assertTrue(s.containsKey(a));
429
        assertTrue(s.contains(b));
431
        assertTrue(s.containsKey(b));
430
        assertTrue(s.contains(c));
432
        assertTrue(s.containsKey(c));
431
433
432
        assertEquals(b, ul.set(1, a));
434
        assertEquals(b, ul.set(1, a));
433
        assertEquals(2, s.size());
435
        assertEquals(2, s.size());
Lines 434-447 Link Here
434
        assertEquals(2, l.size());
436
        assertEquals(2, l.size());
435
        assertEquals(a, l.get(0));
437
        assertEquals(a, l.get(0));
436
        assertEquals(c, l.get(1));
438
        assertEquals(c, l.get(1));
437
        assertTrue(s.contains(a));
439
        assertTrue(s.containsKey(a));
438
        assertFalse(s.contains(b));
440
        assertFalse(s.containsKey(b));
439
        assertTrue(s.contains(c));
441
        assertTrue(s.containsKey(c));
440
    }
442
    }
441
443
442
    public void testCollections304() {
444
    public void testCollections304() {
443
        final List<String> list = new LinkedList<String>();
445
        final List<String> list = new LinkedList<String>();
444
        final SetUniqueList<String> decoratedList = SetUniqueList.setUniqueList(list);
446
        final MapUniqueList<String> decoratedList = MapUniqueList.mapUniqueList(list);
445
        final String s1 = "Apple";
447
        final String s1 = "Apple";
446
        final String s2 = "Lemon";
448
        final String s2 = "Lemon";
447
        final String s3 = "Orange";
449
        final String s3 = "Orange";
Lines 475-481 Link Here
475
    @SuppressWarnings("unchecked")
477
    @SuppressWarnings("unchecked")
476
    public void testCollections307() {
478
    public void testCollections307() {
477
        List<E> list = new ArrayList<E>();
479
        List<E> list = new ArrayList<E>();
478
        List<E> uniqueList = SetUniqueList.setUniqueList(list);
480
        List<E> uniqueList = MapUniqueList.mapUniqueList(list);
479
481
480
        final String hello = "Hello";
482
        final String hello = "Hello";
481
        final String world = "World";
483
        final String world = "World";
Lines 493-502 Link Here
493
        assertFalse(subList.contains("World")); // passes
495
        assertFalse(subList.contains("World")); // passes
494
        assertFalse(subUniqueList.contains("World")); // fails
496
        assertFalse(subUniqueList.contains("World")); // fails
495
497
496
        // repeat the test with a different class than HashSet;
498
        // repeat the test with a different class than HashMap;
497
        // which means subclassing SetUniqueList below
499
        // which means subclassing MapUniqueList below
498
        list = new ArrayList<E>();
500
        list = new ArrayList<E>();
499
        uniqueList = new SetUniqueList307(list, new java.util.TreeSet<E>());
501
        uniqueList = new MapUniqueList307(list, new java.util.TreeMap<E, Integer>());
500
502
501
        uniqueList.add((E) hello);
503
        uniqueList.add((E) hello);
502
        uniqueList.add((E) world);
504
        uniqueList.add((E) world);
Lines 516-522 Link Here
516
    @SuppressWarnings("unchecked")
518
    @SuppressWarnings("unchecked")
517
    public void testRetainAll() {
519
    public void testRetainAll() {
518
        final List<E> list = new ArrayList<E>(10);
520
        final List<E> list = new ArrayList<E>(10);
519
        final SetUniqueList<E> uniqueList = SetUniqueList.setUniqueList(list);
521
        final MapUniqueList<E> uniqueList = MapUniqueList.mapUniqueList(list);
520
        for (int i = 0; i < 10; ++i) {
522
        for (int i = 0; i < 10; ++i) {
521
            uniqueList.add((E)Integer.valueOf(i));
523
            uniqueList.add((E)Integer.valueOf(i));
522
        }
524
        }
Lines 542-548 Link Here
542
        for (int i = 0; i < 5; ++i) {
544
        for (int i = 0; i < 5; ++i) {
543
            list.add((E)Integer.valueOf(i));
545
            list.add((E)Integer.valueOf(i));
544
        }
546
        }
545
        final SetUniqueList<E> uniqueList = SetUniqueList.setUniqueList(list);
547
        final MapUniqueList<E> uniqueList = MapUniqueList.mapUniqueList(list);
546
        for (int i = 5; i < 10; ++i) {
548
        for (int i = 5; i < 10; ++i) {
547
            uniqueList.add((E)Integer.valueOf(i));
549
            uniqueList.add((E)Integer.valueOf(i));
548
        }
550
        }
Lines 561-592 Link Here
561
        assertTrue(uniqueList.contains(Integer.valueOf(8)));
563
        assertTrue(uniqueList.contains(Integer.valueOf(8)));
562
    }
564
    }
563
565
564
    public void testSetCollections444() {
566
    public void testMapCollections444() {
565
        final SetUniqueList<Integer> lset = new SetUniqueList<Integer>(new ArrayList<Integer>(), new HashSet<Integer>());
567
        final List<Integer> list = new ArrayList<Integer>();
568
        final Map<Integer, Integer> map = new HashMap<Integer, Integer>();
569
        final MapUniqueList<Integer> lmap = new MapUniqueList<Integer>(list, map);
566
570
567
        // Duplicate element
571
        // Duplicate element
568
        final Integer obj1 = Integer.valueOf(1);
572
        final Integer obj1 = Integer.valueOf(1);
569
        final Integer obj2 = Integer.valueOf(2);
573
        final Integer obj2 = Integer.valueOf(2);
570
574
571
        lset.add(obj1);
575
        lmap.add(obj1);
572
        lset.add(obj2);
576
        lmap.add(obj2);
573
        lset.set(0, obj1);
577
        lmap.set(0, obj1);
574
        assertEquals(2, lset.size());
578
        assertEquals(2, lmap.size());
575
        assertSame(obj1, lset.get(0));
579
        assertSame(obj1, lmap.get(0));
576
        assertSame(obj2, lset.get(1));
580
        assertSame(obj2, lmap.get(1));
577
581
578
        assertTrue(lset.contains(obj1));
582
        assertTrue(lmap.contains(obj1));
579
        assertTrue(lset.contains(obj2));
583
        assertTrue(lmap.contains(obj2));
580
    }
584
    }
581
585
582
    class SetUniqueList307 extends SetUniqueList<E> {
586
    class MapUniqueList307 extends MapUniqueList<E> {
583
        /**
587
        /**
584
         * Generated serial version ID.
588
         * Generated serial version ID.
585
         */
589
         */
586
        private static final long serialVersionUID = 1415013031022962158L;
590
        private static final long serialVersionUID = 1415013031022962158L;
587
591
588
        public SetUniqueList307(final List<E> list, final Set<E> set) {
592
        public MapUniqueList307(final List<E> list, final Map<E, Integer> map) {
589
            super(list, set);
593
            super(list, map);
590
        }
594
        }
591
    }
595
    }
592
596
Lines 593-606 Link Here
593
    //-----------------------------------------------------------------------
597
    //-----------------------------------------------------------------------
594
    @Override
598
    @Override
595
    public String getCompatibilityVersion() {
599
    public String getCompatibilityVersion() {
596
        return "4";
600
        return "4.FIXME";
597
    }
601
    }
598
602
599
//    public void testCreate() throws Exception {
603
    public void testCreate() throws Exception {
600
//        resetEmpty();
604
        resetEmpty();
601
//        writeExternalFormToDisk((java.io.Serializable) getCollection(), "src/test/resources/data/test/SetUniqueList.emptyCollection.version4.obj");
605
        writeExternalFormToDisk((java.io.Serializable) getCollection(), "src/test/resources/data/test/MapUniqueList.emptyCollection.version4.FIXME.obj");
602
//        resetFull();
606
        resetFull();
603
//        writeExternalFormToDisk((java.io.Serializable) getCollection(), "src/test/resources/data/test/SetUniqueList.fullCollection.version4.obj");
607
        writeExternalFormToDisk((java.io.Serializable) getCollection(), "src/test/resources/data/test/MapUniqueList.fullCollection.version4.FIXME.obj");
604
//    }
608
    }
605
609
606
}
610
}

Return to bug 58740