1

I am turning a HashSet of user-defined objects into an ArrayList of those same objects, i.e. like this:

List<MyObject> myList = new ArrayList<>(myMap.keySet())

I would like to sort this list so that the ordering is the same each time I compile my code.

But, importantly, I don't actually care how these objects are ordered. Therefore I would prefer not to define a Comparator, or have MyObject implement Comparable, if possible. What is the most lightweight way of doing this?

K--
  • 594
  • 1
  • 8
  • 20
  • 1
    What's more lightweight than using a comparator like `Collections.sort(myList, Comparator.comparing(MyObject::hashCode))`? – daniu Jun 17 '20 at 11:31
  • 2
    What do you mean with “each time I compile my code”? Compiling the code has no influence here. Apparently, you mean *running* the code. – Holger Jun 17 '20 at 11:31
  • 2
    @daniu there is no guaranty that this produces the same order on each run. – Holger Jun 17 '20 at 11:32
  • 1
    Just out of curiosity, why do want to do that? – vinicius de novaes Jun 17 '20 at 11:33
  • 1
    @Holger You're right (I assume that's the effect she meant by "each compilation"). I just couldn't use a different instance methods since OP didn't post any. – daniu Jun 17 '20 at 11:35
  • 3
    It’s important to know whether this is about multiple executions of this code within the same runtime or multiple executions of the program, i.e. in different JVM instances. In the latter case, “same ordering” needs a definition of “same object” first. Without these clarifications, the question is unanswerable. – Holger Jun 17 '20 at 11:40
  • @Holger - um. Both? – K-- Jun 17 '20 at 11:40
  • 1
    In that case, as said, you need a definition of what makes one object of a particular runtime the same object of another runtime, as without that definition, it is impossible to say whether an order of one runtime is the same order of another runtime. Is `MyObject@8534ab1b, MyObject@7855291a, MyObject@a078a36f, MyObject@2842f92e` the same order as `MyObject@1e96a8df, MyObject@c6197e78, MyObject@cc1c12e0, MyObject@41be5660`? Yes, No, Why? – Holger Jun 17 '20 at 11:47
  • 1
    If the objects never change then you can just sort them by one or more values e.g. alphabetically. If they are subject to change then you must introduce some unique index. – Igor Flakiewicz Jun 17 '20 at 11:47
  • 1
    Well the easiest way is to do nothing. The order of this `ArrayList` is then the *insertion order*. – MC Emperor Jun 17 '20 at 11:58
  • 1
    Perhaps, you just want a stable, reproducible string representation of the `myList`, so that you can compare the output of, e.g. `System.out.println(myList);`. In that case, `myList.sort(Comparator.comparing(String::valueOf));` would be sufficient. Of course, this assumes that the objects have a meaningful string representation. – Holger Jun 17 '20 at 13:16

1 Answers1

3

But, importantly, I don't actually care how these objects are ordered.

This is exactly what Guava's Ordering.arbitrary() will do:

Returns an arbitrary ordering over all objects, for which compare(a, b) == 0 implies a == b (identity equality). There is no meaning whatsoever to the order imposed, but it is constant for the life of the VM.

However, it specifically doesn't support your requirement for:

I would like to sort this list so that the ordering is the same each time I compile my code.

For that, you'll need to give your objects some kind of identifying state. This could be name, an index of construction order or an explicit order. There is no general way to carry the "same" order across runs without knowing more about your code.

If the "same" order means the order in which your algorithm produced its results, make the Map one that preserves the order of insertion, rather than sorting afterwards. That will give you a deterministic order based on your code's behaviour.

Joe
  • 29,416
  • 12
  • 68
  • 88