I was running into problems with different teams at my employer using different Immutable Collection implementations and wanted to avoid writing code to adapt each Collection
Larry Diamond
ldiamond at ldiamond.com
Tue Feb 2 23:07:38 UTC 2021
I'm looking through the Collections framework and I believe the following
methods
should be changed to take in a "Readable" counterpart:
Collection:
containsAll (Collection<?> c)
addAll (Collection<? extends E> c)
removeAll (Collection<?> c)
retainAll (Collection<?> c)
List:
containsAll (Collection<?> c) // from Collection
addAll (Collection<? extends E> c) // from Collection
addAll (int index, Collection<? extends E> c)
removeAll (Collection<?> c) // from Collection
retainAll (Collection<?> c) // from Collection
copyOf (Collection <> extends E> coll)
Set:
containsAll (Collection<?> c) // from Collection
addAll (Collection<? extends E> c) // from Collection
removeAll (Collection<?> c) // from Collection
retainAll (Collection<?> c) // from Collection
copyOf (Collection <> extends E> coll)
Map:
putAll(Map<? extends K, ? extends V> m)
copyOf(Map<? extends K, ? extends V> map)
Deque:
addAll (Collection<? extends E> c) // from Collection
The following interfaces have been reviewed and I believe no changes to the
files would occur. The interfaces may become changed due to a
superinterface change:
Enumeration
Iterable
Iterator
ListIterator
NavigableMap
NavigableSet
Queue
SortedMap
SortedSet
Spliterator
These are all the interfaces I reviewed, I doubt I know the details of the
Collections
framework nearly as well as anybody else on this distribution list.
Thank you for taking the time to review this proposal, I appreciate your
thought and
feedback.
Larry Diamond
On Mon, Feb 1, 2021 at 8:44 PM Larry Diamond <ldiamond at ldiamond.com> wrote:
> Thank you for taking the time to look over my proposal and give it some
> really good thought.
>
> I really like the idea of calling the interfaces "Readable" rather than
> "Unmodifiable".
> I agree that the every ArrayList is "Immutable" since that clearly isn't
> my intent here,
> and I like the "Readable" term much better than "Immutable" or
> "Unmodifiable" and you've
> clearly internalized what I was thinking about and are very familiar with
> the Guava and Eclipse
> attempts to implement this concept. (and of yeah Readable is a lot easier
> to spell than Unmodifiable!)
>
> There are definitely some methods on the existing interfaces that would
> need to change
> types to accept ReadableCollection rather than Collection. I'll compile
> a list so at least
> everybody can take a look at how big of a change that would be.
>
> The for-loop connection to Iterable would need to change to
> ReadableIterable.
> I'm not sure how big of a job that is to change that, but since Iterable
> would extend ReadableIterable
> no existing code should be broken by that change.
>
> My original idea was that Immutability is a "view" of the underlying
> Collection and so changes
> to the underlying Collection would change the Immutable view.
> My original goal is to prevent software defects by allowing "readers" of a
> Collection to have different rights
> to that Collection than "owners" - to pass in an Immutable view of a
> Collection into a method and be confident
> that method could not change the Collection, and for the readers of that
> Collection to be aware of that at compile
> time and not run time.
>
> public void myMethod (Set<Something> mySet) {
> ReadableSet <Something> myReadableSet = mySet;
> boolean whatever = someOtherMethod (myReadableSet);
>
> I know that someOtherMethod will never modify mySet and a developer
> attempting
> to do so will be blocked by the compiler. It certainly does not prevent
> another thread from
> modifying mySet, just like today with a ConcurrentSkipListSet. The
> difference is that the developer
> is preventing from compiling code that damages mySet, preventing the
> introduction of unexpected behavior
> from future code after the original developers have moved onto other
> projects.
>
> My original intent was to have an "unmodifiable view" rather than a
> "shallowly immutable" Collection.
> If somebody wants to have a "shallowly immutable" Collection, that can
> make a "unmodifiable view" of
> what they want in their Collection and then throw away the original
> Collection reference and only use the
> "unmodifiable view" in their code.
>
> Set<Something> mySet = loadFromDatabase();
> ReadableSet<Something> myReadableSet = mySet;
> mySet = null;
>
> As regards to the List.of() methods and similar methods, I've proposed
> List.uof() (Unmodifiable Of,
> perhaps now rof() to say ReadableOf methods in the Readable interfaces
> that would have default
> implementations in the existing interfaces to return the value of the
> existing of() method.
> ReadableList<String> myList = ReadableList.rof ("A", "B", "C");
> would be the same as
> ReadableList<String> myList = List.of ("A", "B", "C");
> and I hope that the default implementations in List reduce the need for
> any implementing class
> from needing to change - that is a goal of this design.
>
> I agree that when the Collections framework was first created that these
> classes wouldn't have made sense.
> With (at least) three well known high quality attempts at hitting this
> target, there's clearly some different
> opinions in the community. I think the use cases for Java applications
> are much different now than they were
> when the framework was written, many of them thanks to the success of
> Java. One of the documents that has
> been referred to is
> https://docs.oracle.com/javase/8/docs/technotes/guides/collections/designfaq.html#a2
> which
> states that in the case of a programming error that the program should
> halt. In the command line use cases
> when the framework was written, I think that was a very reasonable
> decision and reasonable behavior, and
> now we've all no doubt had more than a few conversations about defensive
> programming - I think the newer
> use cases warrant a reconsideration of what I think was the right decision
> at the time. Software defects are
> much more common now and I can't think of a single very large application
> that does not have some defects
> in them somewhere, even if we don't see them very often. Security
> related defects are particularly troublesome
> and were not so much of an issue before we all had publicly accessible
> RESTFul endpoints in our applications.
>
> Thank you both very much for taking the time to discuss my suggestion in
> extremely intelligent depth.
> I greatly appreciate your feedback and consideration.
>
> I will review the interfaces and come up with a list of methods where the
> signature might change to accept
> "Readable" interfaces.
>
> Thank you very much
> Larry Diamond
>
>
>
>
>
>
>
>
>
> On Mon, Feb 1, 2021 at 7:17 PM Stuart Marks <stuart.marks at oracle.com>
> wrote:
>
>> As Remi pointed out, retrofitting the interfaces this way would imply
>> that ArrayList
>> implements UnmodifiableCollection. (This seems semantically wrong in the
>> first
>> place, but it might be mitigated by renaming things to ReadableCollection
>> etc.)
>>
>> Another point is that UnmodifiableCollection isn't a Collection, so
>> adding its
>> elements to an existing collection via myArrayList.addAll(unmodcoll)
>> would no longer
>> work without some additional adaptation.
>>
>> Additionally, UnmodifiableCollection would implement UnmodifiableIterable
>> but not
>> Iterable, so it would no longer be possible to iterate using a for-loop.
>> Again, not
>> without additional adaptation.
>>
>> I've written some about this issue here:
>>
>> https://stackoverflow.com/a/57926310/1441122
>>
>> One alternative this SO answer doesn't cover is having no type
>> relationship between
>> UnmodifiableCollection and Collection, similar to the way Eclipse
>> Collections does
>> it. That's another stable point in the design space, and it has a bunch
>> of different
>> tradeoffs. It also requires the addition of a bunch of adapters between
>> the hierarchies.
>>
>> A central decision is whether "unmodifiable" allows unmodifiability to be
>> cast away,
>> whether it permits modification only via another reference (an
>> "unmodifiable view"),
>> or whether it indicates the underlying collection itself is unmodifiable
>> ("shallowly
>> immutable"). Closely related is the issue of what to do about the return
>> type of
>> methods like List.of() and Collections.unmodifiableList() and related
>> methods.
>>
>> Remi noted previously that the idea of unmodifiable collection interfaces
>> was
>> rejected from the initial design. That doesn't mean it's a bad idea and
>> that they
>> can never be added. Indeed, proposals and questions in this area do come
>> up from
>> time to time. The problem is that doing this (for whatever definition of
>> "this") is
>> harder than it seems at first glance, and the benefits provided have
>> never been
>> quite able to justify the additional complexity this would add to the
>> platform.
>>
>> s'marks
>>
>>
>>
>> On 1/31/21 2:10 PM, Larry Diamond wrote:
>> > Wow thanks for getting back to me so quickly. I'll read over the
>> existing
>> > conversation. Thank you very much
>> >
>> > On Sun, Jan 31, 2021 at 4:19 PM Remi Forax <forax at univ-mlv.fr> wrote:
>> >
>> >> Hi Larry,
>> >> this design was considered and rejected when the collection API vas
>> >> introduced in JDK 1.2
>> >> see
>> >>
>> https://mail.openjdk.java.net/pipermail/core-libs-dev/2020-May/066245.html
>> >>
>> >> Furthermore, if List extends ImmutableList, it means that ArrayList
>> >> implements ImmutableList which is just plain wrong.
>> >> Consider the following code
>> >> record Foo(ImmutableList<String> list) { }
>> >> var arrayList = new ArrayList<String>();
>> >> var foo = new Foo(arrayList);
>> >> System.out.println(foo.list()); // []
>> >> arrayList.add("oops");
>> >> System.out.println(foo.list()); // [oops]
>> >>
>> >> regards,
>> >> Rémi
>> >>
>> >> ----- Mail original -----
>> >>> De: "Larry Diamond" <ldiamond at ldiamond.com>
>> >>> À: "jdk-dev" <jdk-dev at openjdk.java.net>
>> >>> Envoyé: Dimanche 31 Janvier 2021 21:28:33
>> >>> Objet: I was running into problems with different teams at my employer
>> >> using different Immutable Collection
>> >>> implementations and wanted to avoid writing code to adapt each
>> Collection
>> >>
>> >>> I was thinking of submitting a proposal for UnmodifiableCollections
>> for
>> >>> Java.
>> >>>
>> >>> I wrote up a first draft of a JEP for this.
>> >>>
>> >>> What do you think?
>> >>>
>> >>> Thank you very much
>> >>> Larry Diamond
>> >>
>>
>
More information about the jdk-dev
mailing list