<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<div class="moz-cite-prefix">On 1/17/2025 5:49 PM, David Alayachew
wrote:<br>
</div>
<blockquote type="cite" cite="mid:CAA9v-_NKY77_Pu=FTUhNPXsuP84ykCs-Au03LDmx+2QT4ZPVew@mail.gmail.com">
<p dir="ltr">It definitely helps.</p>
<p dir="ltr">I guess my next question is, there is no bridge
method, which is why this fails. Why not add a bridge method?
What is stopping Java from doing this?</p>
</blockquote>
<p><br>
</p>
<p>The default response to the question "Should we fundamentally
change how Java source files are compiled into class files?" is
"No." ;-)<br>
<br>
Covariant returns "work" for instance methods for several reasons.
Such behavior is expected from object-oriented type theory where
it is sound for an overridden method to return a more specialized
type in a subtype. Also, when presented with a single snapshot of
the type hierarchy, as during compilation, it is relatively
straightforward for the compiler to compute which bridge methods
are needed, roughly look over the superclass and implemented
interfaces for methods with the same name and set of arguments,
but a different return type.</p>
<p>Muddier on both accounts for how static methods would be handled
by such a bridge method feature.<br>
</p>
<p>-Joe<br>
</p>
<p><br>
</p>
<blockquote type="cite" cite="mid:CAA9v-_NKY77_Pu=FTUhNPXsuP84ykCs-Au03LDmx+2QT4ZPVew@mail.gmail.com">
<p dir="ltr">And to be clear, it is obvious to me that
SewuencedSet.of is the right answer. I am just trying to
understand the point you raised.</p>
<br>
<div class="gmail_quote gmail_quote_container">
<div dir="ltr" class="gmail_attr">On Fri, Jan 17, 2025, 8:14 PM
Joseph D. Darcy <<a href="mailto:joe.darcy@oracle.com" moz-do-not-send="true" class="moz-txt-link-freetext">joe.darcy@oracle.com</a>>
wrote:<br>
</div>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div>
<p><br>
</p>
<div>On 1/17/2025 5:00 PM, David Alayachew wrote:<br>
</div>
<blockquote type="cite">
<div dir="auto">
<p dir="ltr">Thanks for the corrections folks. I was
thinking from the perspective of LSP. I now see that
there is the performance perspective to consider too.</p>
<p dir="ltr">Now that said, I don't understand your
comment Joe Darcy. Could you explain it in more
detail?</p>
</div>
</blockquote>
<p>Say you compile your code against JDK 24 and use the
1-argument Set.Of() method. For that call site, your class
file will refer to a method using information akin to</p>
<p> "In the class java.util.Set, a method named "of" that
*returns a java.util.Set* and take a java.lang.Object as
an argument"</p>
<p>(The generic information is basically erased in the class
file, hence Set rather than Set<E> and Object rather
than E.)</p>
<p>If we were then in JDK 25 to replace in java.util.Set<br>
<br>
static <E> Set<E> of(E e1){...}<br>
<br>
with</p>
<p> static <E> SequencedSet<E> of(E e1){...}</p>
<p>when your class file ran against JDK 25, there would be
no method</p>
<p> "In the class java.util.Set, a method named "of" that
*returns a java.util.Set* and take a java.lang.Object as
an argument"</p>
<p>for your class to call and the linkage would fail.</p>
<p>For static methods, the change is equivalent to removing
a method and adding back a different, same-named method.</p>
<p>HTH,<br>
</p>
<p>-Joe<br>
</p>
<p><br>
</p>
<blockquote type="cite">
<div dir="auto">
<p dir="ltr">My initial pick up of your comment is that,
the parameter types and the return types of a method
must match the types exactly between releases,
otherwise there are no bridge methods FOR STATIC
TYPES. But as for why, I don't understand.</p>
<p dir="ltr">I know that static methods are not so much
inherited as they are just given as is (hence why
there is not really a static abstract method). But I
don't quite see the line connecting that with no
bridge methods for static. Maybe I don't understand
bridge methods well enough.</p>
</div>
<br>
<div class="gmail_quote">
<div dir="ltr" class="gmail_attr">On Fri, Jan 17, 2025,
12:32 PM Joseph D. Darcy <<a href="mailto:joe.darcy@oracle.com" rel="noreferrer noreferrer noreferrer" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">joe.darcy@oracle.com</a>>
wrote:<br>
</div>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div>
<div>On 1/16/2025 11:26 PM, Rafael Winterhalter
wrote:<br>
</div>
<blockquote type="cite">
<div dir="ltr">
<div>Would it even be possible to change the
return types of Set.of(...) and Map.of(...)
without breaking binary compatibility?</div>
</div>
</blockquote>
<p><br>
</p>
<p>In short, no.</p>
<p>The methods in question are *static* methods.
Switching to covariant overrides with more precise
return types works for subclasses because of
bridge methods.</p>
<p>In a bit more detail, in a covariant override a
single method in the source code gets translated
into multiply methods in the class file.
References to methods in the class file use the
argument types and return type so if an old class
file refers to the previously declared
source-level return type, there is the bridge
method present to be linked to (for binary
compatibility) and then executed.<br>
</p>
<p>-Joe<br>
</p>
<p><br>
</p>
<blockquote type="cite">
<div dir="ltr">
<div><br>
</div>
<div>I also think that the randomization of
Set.of(...) and Map.of(...) is a good property
as it uncovers bugs early if one relies on
iteration order. This especially since those
methods are often used in tests where
production code would use a proper HashSet
which cannot guarantee iteration order for
good reasons. Exactly here I think the new
interfaces are a good addition as it uncovers
such misconceptions. If code relies on
insertion order, providing a Set.of(...) does
no longer compile, what is a good thing.<br>
</div>
<div><br>
</div>
<div>To me, adding SequencedSet.of(...) and
SequencedMap.of(...) sounds like the right
approach, with implementations similar to that
of Set.of(...) and Map.of(...). As for
megamorphism, I think the chance of encounter
at a call site is similar, as Set12 and SetN
from the Set interface are typically combined
with HashMap. As for a possible SequencedSet12
and SequencedSetN, I think they would normally
be seen with LinkedHashSet.</div>
<div><br>
</div>
<div>Best regards, Rafael<br>
</div>
</div>
<br>
<div class="gmail_quote">
<div dir="ltr" class="gmail_attr">Am Fr., 17.
Jan. 2025 um 00:36 Uhr schrieb David Alayachew
<<a href="mailto:davidalayachew@gmail.com" rel="noreferrer noreferrer noreferrer noreferrer" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">davidalayachew@gmail.com</a>>:<br>
</div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<p dir="ltr">I should also add, the
documentation went out of their way to
specify that iteration order is unspecified.</p>
<p dir="ltr">Also, I see Rémi's comment, but
that's even more unconvincing to me.</p>
<p dir="ltr">Map.of has an upper limit of 10
entries, and Map.ofEntries has an upper
limit of that Java max file size limit
thing. You all know what I am talking about.</p>
<p dir="ltr">Point is, both of these static
factories were meant to be used on a small
number of entries. If it truly has just been
not done until now, then the bug database
will confirm that easily.</p>
<p dir="ltr">When I get back, I can check
myself.</p>
<br>
<div class="gmail_quote">
<div dir="ltr" class="gmail_attr">On Thu,
Jan 16, 2025, 6:25 PM David Alayachew <<a href="mailto:davidalayachew@gmail.com" rel="noreferrer noreferrer noreferrer noreferrer" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">davidalayachew@gmail.com</a>>
wrote:<br>
</div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<p dir="ltr">I guess let me ask the
obvious question.</p>
<p dir="ltr">Chesterton's fence -- why
wasn't this done before? I refuse to
believe that this idea wasn't thought up
years ago, which leads me to believe
there was a reason that it hasn't been
done.</p>
<p dir="ltr">Is there any way we can look
this up in the bug database or
something?</p>
<br>
<div class="gmail_quote">
<div dir="ltr" class="gmail_attr">On
Thu, Jan 16, 2025, 2:28 PM Jens
Lideström <<a href="mailto:jens@lidestrom.se" rel="noreferrer noreferrer noreferrer noreferrer noreferrer" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">jens@lidestrom.se</a>>
wrote:<br>
</div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Having
the result Map.of and Set.of preserve
the insertion order would <br>
often be convenient.<br>
<br>
More often than not programs iterate
over the contents of a maps and <br>
sets at some point. For example to
present the values in a GUI, for <br>
serialisation, or even for error
printouts. In all those cases having a
<br>
fixed iteration order is much better
than having a random iteration <br>
order.<br>
<br>
Often it is even a subtle bug to have
a random iteration order. For <br>
example, I ran in to a situation where
jdeps printed a error message <br>
containing a list of modules. But the
list was in a different order on <br>
each run of the program! It took me a
while to figure out that it was <br>
actually the same list. A possible
explanation is that jdeps is <br>
implemented using Map.of or Set.of.<br>
<br>
Because of this I think I would be
better if the most commonly used <br>
standard collection factories produced
collections with a fixed <br>
iteration order.<br>
<br>
Guavas ImmutableMap and ImmutableSet
also preserve insertion order.<br>
<br>
Regards,<br>
Jens Lideström<br>
<br>
<br>
On 2025-01-16 08:44, Remi Forax wrote:<br>
<br>
> -------------------------<br>
> <br>
>> From: "Rafael Winterhalter"
<<a href="mailto:rafael.wth@gmail.com" rel="noreferrer noreferrer noreferrer noreferrer noreferrer noreferrer" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">rafael.wth@gmail.com</a>><br>
>> To: "core-libs-dev" <<a href="mailto:core-libs-dev@openjdk.java.net" rel="noreferrer noreferrer noreferrer noreferrer noreferrer noreferrer" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">core-libs-dev@openjdk.java.net</a>><br>
>> Sent: Thursday, January 16,
2025 8:13:17 AM<br>
>> Subject: Factory methods for
SequencedSet and SequencedMap<br>
> <br>
>> Hello,<br>
> <br>
> Hello,<br>
> <br>
>> I am happily taking
SequencedSet and SequencedMap into
use, but one <br>
>> inconvenience I encounter is
the lack of factory methods for the
two.<br>
>> In code where many (initial)
collections have zero or one element
(for <br>
>> later aggregation), I now
write Set.of()/Set.of(one) and <br>
>> Map.of()/Map.of(key, value),
as it makes the code shorter and more
<br>
>> readable. Those collections
are of course implicitly sequenced,
but <br>
>> now I must make the variable
type of the surrounding monad Set and
<br>
>> Map, and simply assume that a
LinkedHashSet or LinkedHashMap is used
<br>
>> when a collection of more
than one element is set, without
requiring <br>
>> the interface type. This does
not require any type casting, as I
rely <br>
>> on the iteration order only,
but the code loses some of its <br>
>> expressiveness.<br>
>> I did not find any discussion
around introducing factories for <br>
>> SequencedSet.of(...) and
SequencedMap.of(...), similar to those
that <br>
>> exist in the Set and Map
interfaces. Was this ever considered,
and if <br>
>> not, could it be?<br>
> <br>
> Thanks for re-starting that
discussion, it was talked a bit, but
not as <br>
> it should be.<br>
> <br>
> So the issue is that currently we
do not have any compact, unmodifiable
<br>
> and ordered Set/Map
implementation,<br>
> one use case is when you have
data that comes from a JSON object as
a <br>
> Map and you want to keep the
inserted order, if by example the JSON
is <br>
> a config file editable by a
human, an other example is in unit
tests <br>
> where you want to help the dev to
read the output of the test so the <br>
> code that creates a Set/Map and
what is outputed by the test should be
<br>
> in the same order.<br>
> Currently there is no good
solution for those use cases because <br>
> Set|Map.copyOf() does not keep
the ordering.<br>
> <br>
> I see two solutions, either we
add a new <br>
>
SequenceSet|SequenceMap.of/copyOf, or
we change the impleemntation of <br>
> Set|Map.of()/copyOf().<br>
> Python had gone for the latter
solution, which has the advantage a <br>
> being simple from the user POV,
but from an algorithm expert POV, a
Set <br>
> and a SequencedSet are different
concepts we may want to emphasis ?<br>
> <br>
>> Best regards, Rafael<br>
> <br>
> regards,<br>
> Rémi<br>
</blockquote>
</div>
</blockquote>
</div>
</blockquote>
</div>
</blockquote>
</div>
</blockquote>
</div>
</blockquote>
</div>
</blockquote>
</div>
</blockquote>
</body>
</html>