List<E>.add always returns true (or throws)?
http://download.java.net/jdk6/docs/api/java/util/List.html#add(E)
"Returns:
true (as specified by Collection.add(E))"
but http://download.java.net/jdk6/docs/api/java/util/Collection.html#add(E)
"Returns:
true if this collection changed as a result of the call"
and also says, "(Returns false if this collection does not permit duplicates and already contains the specified element.)"
I am implementing a list that doesn't allow duplicate elements -- which the List<E> doc says "is not inconceivable ... but we expect this usage to be rare." My rarity notwithstanding, I don't understand the parenthetical remark in the Returns doc for List, and I don't know whether to return false or throw if an attempt is made to add a duplicate to my list.
I would say that you should return "false"
Indeed the javadoc about add in List interface:
return true (as per the general contract of the Collection.add method).
should be read (in my opinion) : simply respect the general contract of Collection.add method.
Of course, you could also throw an IllegalArgumentException (as said in Collection.add throw IllegalArgumentException - some aspect of this element prevents it from being added to this collection.)
*but* as the javadoc said also:
"If a collection refuses to add a particular element for any reason other than that it already contains the element, it must throw an exception (rather than returning false). This preserves the invariant that a collection always contains the specified element after this call returns".
--> One can guess that another invariant of the collection is that it does NOT contain the specified element if an exception is thrown after an add. This is true for ClassCastException, NullPointerException and UnsupportedOperationException.
So better return false than throw an exception.
> I am implementing a list that doesn't allow duplicate
> elements -- which the List<E> doc says "is not
> inconceivable ... but we expect this usage to be
> rare." My rarity notwithstanding, I don't understand
> the parenthetical remark in the Returns doc for List,
> and I don't know whether to return false or throw if
> an attempt is made to add a duplicate to my list.
I'd say you are about to implement a Set and not a List.
> I'd say you are about to implement a Set and not a List.I agree
> > I'd say you are about to implement a Set and not a
> List.
>
> I agree
There is that set-like odor about non-duplicates. But there's the list-like odor about order. The javadoc mentions that a Set might be ordered, and that a list might not allow duplicates, although either of those is implied to be exceptional -- the List more so.
Originally (last night) I chose List because ArrayList seemed much the best implementation to wrap. Now in the light of day I see no reason that an implementation of Set couldn't wrap an ArrayList. Right?
If that is your choice of implementation, sure you can do it like that. :)A Set not being ordered seems natural, but that does not hinder to implement an OrderedSet (as there also is a SortedSet interface and its TreeSet implementation in the Collections Framework.)
> Originally (last night) I chose List because
> ArrayList seemed much the best implementation to
> wrap. Now in the light of day I see no reason that
> an implementation of Set couldn't wrap an ArrayList.
> Right?
Right.
How about this:
One of the standard Set implementation is HashSet. It uses a HashMap (with dummy values) to de-duplicate the set. You could write your own Set implementation very much like HashSet, but backed instead with a LinkedHashMap which maintains insertion order (like a List does).
> How about this:
>
> One of the standard Set implementation is HashSet. It
> uses a HashMap (with dummy values) to de-duplicate
> the set. You could write your own Set implementation
> very much like HashSet, but backed instead with a
> LinkedHashMap which maintains insertion order (like a
> List does).
At first blush it seems like overkill for my purpose, but I'll think about it more.
Meanwhile, a question arose on my reading of the javadoc on LinkedHashMap. It says, "It can be used to produce a copy of a set that has the same order as the original, regardless of the original set's implementation:void foo(Set m) {
Set copy = new LinkedHashSet(m);
...
}
I don't understand how the LinkedHashSet copy constructor can produce a copy that "has the same order" unless the implementation of the original set -- in particular, I guess, its iterator -- guarantees some ordering. But then that would contradict "regardless of the original set's implementation."
Err... stupid me! I totally forgot about LinkedHashSet which looks like it will solve your problem directly, with no code!
> Meanwhile, a question arose on my reading of the
> javadoc on LinkedHashMap. It says, "It can be used
> to produce a copy of a set that has the same order as
> the original, regardless of the original set's
> implementation:>void foo(Set m) {
>Set copy = new LinkedHashSet(m);
>...
> }
I don't understand how the LinkedHashSet copy
> constructor can produce a copy that "has the same
> order" unless the implementation of the original set
> -- in particular, I guess, its iterator -- guarantees
> some ordering. But then that would contradict
> "regardless of the original set's implementation."
Looking at the implementation, I would suggest that the JavaDoc is poorly worded. What it means is that this copy constructor will copy everything out of the first set into the new set and the order of the new set will be consistent with the order of the elements returned by the first set's iterator. (Which, of course, is likely to be undefined for the majority of Set implementations.)
