-
Notifications
You must be signed in to change notification settings - Fork 6.2k
8368178: Add specialization of SequencedCollection methods to emptyList, singletonList and nCopies #27406
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
…yList, singletonList and nCopies
👋 Welcome back tvaleev! A progress list of the required criteria for merging this PR into |
❗ This change is not yet ready to be integrated. |
Webrevs
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a very sensible change; thanks! The only small, orthogonal quibble inline.
* questions. | ||
*/ | ||
|
||
/** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A jtreg comment styled as a javadoc comment is one of my pet peeves. IDE and javac (since JDK 23) treats it as a javadoc comment. For example, such a comment has unknown javadoc tags, or may be considered dangling (which is what happens in your case).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the review. I copied the comment from another test file and was not sure whether an extra asterisk is important for jtreg. You're right, it looks like it can be omitted.
Have you considered something like this? diff --git a/src/java.base/share/classes/java/util/ImmutableCollections.java b/src/java.base/share/classes/java/util/ImmutableCollections.java
index 38cc45122a2..d8c3499a958 100644
--- a/src/java.base/share/classes/java/util/ImmutableCollections.java
+++ b/src/java.base/share/classes/java/util/ImmutableCollections.java
@@ -352,7 +352,7 @@ public boolean contains(Object o) {
@Override
public List<E> reversed() {
- return ReverseOrderListView.of(this, false);
+ return size() < 2 ? this : ReverseOrderListView.of(this, false);
}
IndexOutOfBoundsException outOfBounds(int index) {
@@ -636,6 +636,11 @@ public int lastIndexOf(Object o) {
}
}
+ @Override
+ public List<E> reversed() {
+ return size() == 1 ? this : super.reversed();
+ }
+
@java.io.Serial
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
throw new InvalidObjectException("not serial proxy"); |
…yList, singletonList and nCopies
@pavelrappo re Re @SuppressWarnings("unchecked")
@Override
public List<E> reversed() {
return e1 == EMPTY ? this : new List12<>((E) e1, e0);
} This way, we have fewer indirections and always return the instance of |
One more concern is that |
Your comments are good and thought-through. When dealing with classes like that, it's time to bring a microscope and be concerned with as many aspects as possible. As for the first comment, List.of and List.copyOf do not specify the class whose instance they return, or even if and how that class overrides
As for serializability, it also bugs be. Unmodifiable lists are designed to be consistent and strict. Even though the spec clearly says that it's a bad idea to serialize an unkown list, if a list is serializable some of the times but not others, it might hide bugs:
I defer this serializability issue to @stuart-marks. |
I'll slightly refine my List12 suggestion for your consideration: @Override
public List<E> reversed() {
return e1 == EMPTY ? this : ReverseOrderListView.of(this, false);
} |
On a second thought, no, it is not a specification for List clients. It's a specification for List implementors, so that they can decide if and how they override this method. Clients or implementors don't need to abide by it. Although, I now wonder why the default implementation is like that. Is the roundtrip property important? |
Perhaps even that is not a mystery. If a view has a reference to the original list anyway, why not use it? |
Yes, implSpec describes the implementation of a concrete default method without requiring anybody to follow the same restrictions. And you're right, returning the original collection is the easiest and most optimal thing one can do. So I think we are not restricted to return this from this.reversed().reversed(). Serialization is already inconsistent. We can't say that the result of reversed() is never serializable, because reversed().reversed() call may again return the serializable collection. In any case, let's wait for @stuart-marks opinion. |
In theory, |
@minborg public interface List<E> extends SequencedCollection<E> { ... } For public static final <K,V,M extends Map<K, V> & SequencedMap<K, V>> M emptyMap() { ... } But it looks ugly. |
@amaembo
An empty map could also "incidentally" implement |
@minborg as JLS 13.4.15 says,
Changing the result type from |
Thanks for that JLS reference, Tagir. @minborg, one would think they can make a method accept wider arguments or return narrower results. After all, it matches basic subtype intuitions. Yet, one cannot do that; they will get java.lang.NoSuchMethodError from code that uses the old method. FWIW, I tripped on it myself a few times. |
Yeah, I get that. Another alternative would be not to expose the type in the API, but instead let the map instance returned from the method implement |
|
||
@Override | ||
public List<E> reversed() { | ||
return this; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Java indentation is 4 spaces. tnx.
Hm, a lot of issues to try to address. :-) First, the initial proposal of adding overrides to EmptyList, SingletonList, and CopiesList is reasonable. No complications there. On the serializablity of reversed views: in general, the view collections aren't serializable. This also includes things like subList, entrySet, and so forth. The design intent is mostly that they be used temporarily for iteration or copying, and typically aren't stored as the state of some other object. Now that doesn't prohibit a reversed view from being serializable. As Tagir noted, if a list is serializable, and While the spec of the reversed() method is silent on serializability, List.copyOf()'s spec includes a bunch of requirements including serializability, so it pretty much needs to make a copy reversed views that aren't serializable. Finally, I think you straightened it out, but as you noted, the |
Please review this small change. If you have more ideas which classes may miss specializations of SequencedCollection methods, I can add them to this PR as well.
Progress
Issue
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/27406/head:pull/27406
$ git checkout pull/27406
Update a local copy of the PR:
$ git checkout pull/27406
$ git pull https://git.openjdk.org/jdk.git pull/27406/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 27406
View PR using the GUI difftool:
$ git pr show -t 27406
Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/27406.diff
Using Webrev
Link to Webrev Comment