----- Mail original -----
> De: "Stuart Marks" <stuart.ma...@oracle.com>
> À: "Remi Forax" <fo...@univ-mlv.fr>
> Cc: "core-libs-dev" <core-libs-dev@openjdk.java.net>
> Envoyé: Jeudi 5 Mai 2016 08:32:08
> Objet: Re: RFR(m): 8139233 add initial compact immutable collection 
> implementations
> 
> On 5/4/16 1:38 AM, Remi Forax wrote:
> > nice work !
> 
> Spoken like a true university professor: "nice work" followed by 100 lines of
> criticism. :-)

professional bias :)

> 
> > first, all classes should be final otherwise, they are not truly immutable
> > and all arrays should be marked as @Stable.
> 
> OK, I'll make the classes final.
> 
> On @Stable, I had a chat with Paul Sandoz about this, and he suggested
> holding
> back from adding this. Its semantics are quite particular and are subject to
> change, and widespread use could easily turn into misuse.

the third item of an immutable list stored in a static final should be a 
constant, no ?

> 
> > List0, List1,
> >   why not using Collections.emptyList(), Collections.singletonList() here ?
> 
> Serialization compatibility with future versions. I want all of these to
> serialize to the same serial proxy in JDK 9, so that in JDK 9+ they can be
> deserialized to whatever equivalent implementation classes exist in that
> version
> of the JDK. For example, there might be a single field-based implementation
> that
> covers a small range of sizes, or an implementation using value types.

ok !

> 
> > ListN:
> >   - i don't think that extending AbstractList is a good idea here,
> >     AbstractList provide the failfast/modCount mecanism not needed here.
> >     Moreover, i think you should have some overriden methods on par with
> >     Arrays.asList()
> >     (i.e. a custom isEmpty, toArray, indexOf, contains, iterator,
> >     spliterator and forEach)
> >     otherwise people will use Arrays.asList just because it's faster :(
> 
> The implementations all extend AbstractList/Set/Map mainly for implementation
> convenience. This way it makes it easy to add and remove implementations
> tailored for specific sizes, since so much code is shared with the abstract
> superclasses. But they do come with some baggage, as you point out. As the
> set
> of implementation classes settles down, it would make more sense to override
> more methods, and refactor to handle sharing, at which point maybe the
> dependence on the abstract superclasses can be severed.

The problem is that AbstractList is a public class, removing it from the 
hierarchy is not a backward compatible change,
so it's not something that can be changed as an after through.

> 
> >   - in the constructor, you should use a local variable here,
> >         @SafeVarargs
> >         ListN(E... input) {
> >             // copy and check manually to avoid TOCTOU
> >             @SuppressWarnings("unchecked")
> >             E[] elements = (E[])new Object[input.length]; // implicit
> >             nullcheck of input
> >             for (int i = 0; i < input.length; i++) {
> >                 elements[i] = Objects.requireNonNull(input[i]);
> >             }
> >             this.elements = elements;
> >         }
> 
> Nice. Will fix.
> 
> > List2:
> >   - same as for ListN, should not inherits from AbstractList.
> >   - i wonder why iterator() is not overriden like with Set2.
> 
> Bringing up a List implementation with AbstractList requires only overriding
> get() and size(), but not iterator(). On the other hand, bringing up a Set
> implementation using AbstractSet requires overriding only iterator() and
> size().

I think you will have to override iterator anyway (for the same reason the 
result of Arrays.asList() override the iterator). 

> 
> > Set2:
> >   - again, here, i don't think that inheriting from AbstractSet is a good
> >   idea.
> >   - in the iterator, pos (position ?) should be private and next() can be
> >   written without the '+=',
> >                 public E next() {
> >                     if (pos == 0) {
> >                         pos = 1;
> >                         return e0;
> >                     } else if (pos == 1) {
> >                         pos = 2;
> >                         return e1;
> >                     } else {
> >                         throw new NoSuchElementException();
> >                     }
> >                 }
> >   - the iterator should not be defined as inner class (with a reference to
> >   Set2) but
> >     be defined as a static class that contains a copy of e1 and e2,
> >     this will save an indirection and avoid to keep a link on the Set if it
> >     is transient.
> 
> Good fixes, thanks. Some of this is stuff left over from when there were
> field-based implementations with larger sizes.
> 
> > SetN:
> >   - in the constructor, use a local variable like for ListN
> >   - the @SuppressWarnings for contains is wrong, probe should take an
> >   Object, not an E.
> 
> Ah, nice cleanup.
> 
> >   - the iterator should not be an inner class like Set2 and take the array
> >   as parameter.
> >     idx should be private. Instead of doing the loop in hasNext and next,
> >     the loop should
> >     be done once in the constructor and in next. So the code of hasNext
> >     will be simple
> >     and the JIT will be able to fold a call to hasNext() followed by a call
> >     to next().
> 
> OK, I'll look at this.
> 
> >    - i don't understand how the serialization can work given that the SALT
> >    may be different between two VMs
> 
> The salt is XORed with the element's hash to determine the position in the
> collection's array. Serializing it writes all the objects in the array from
> left
> to right, but we don't actually care what the order is. Upon deserialization,
> the objects' hash values are XORed with the deserializing JVM's salt and
> (probably) end up in different positions in the array of the newly
> deserialized
> collection. But again we don't care where they end up.
> 
> Same goes for MapN's keys and values.

ok, i will re-review that code later ...

> 
> > MapN:
> >   - see SetN :)
> 
> :-)
> 
> > SerialProxy:
> >   - I believe the class SerialProxy should be public, no ?
> 
> No, the proxy object can and usually should be private. What's missing is a
> doc
> comment specifying the serial format. This should have an "@serial include"
> tag,
> which will cause the doc comment to end up in the serialized-form.html file.
> This works even if the proxy class itself is private.
> 
> This work is tracked by JDK-8133977.
> 
> >   - The constructor should take a Object... to simplify all calls in the
> >   different writeReplace.
> 
> Good idea.
> 
> >   - fields flags and array should be private
> 
> OK.
> 
> Thanks for all the comments! I'll work on an updated webrev and post it soon.
> 
> s'marks
> 
> 

Rémi

Reply via email to