<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    <p><br>
    </p>
    <div class="moz-cite-prefix">On 1/17/2025 5:00 PM, David Alayachew
      wrote:<br>
    </div>
    <blockquote type="cite" cite="mid:CAA9v-_Nxrak+5VgtjoKLV3rQH=S7EHb9ZT__1Qq9A3-_k5Zo4g@mail.gmail.com">
      
      <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" cite="mid:CAA9v-_Nxrak+5VgtjoKLV3rQH=S7EHb9ZT__1Qq9A3-_k5Zo4g@mail.gmail.com">
      <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" 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" 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" 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" 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" 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" 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>
  </body>
</html>