3

I want to generate UUIDs based on objects. Objects that are equal need to have the same UUID.

I read about the type 3 UUIDs whose value is based on a name and namespace. java.util.UUID has a nameUUIDFromBytes method that takes a byte array as argument.

So I was thinking of serializing my objects into byte arrays and feeding those to the nameUUIDFromBytes method.

But I am confused about that namespace aspect of the UUID. Does that mean the UUID will be different when generated on another machine?

What is the best way to generate UUIDs such that when obj1.equals(obj2) == true, then uuid1.equals(uuid2) == true even when uuid1 is generated on another machine than uuid2?

EDIT: to those who voted this as a duplicate of how to implement a hashCode, please reopen this. I am asking about UUIDs, not hashCodes. Unless you think the best way to generate UUIDs is to use a hashCode. If so, please write an answer as to why that is the best way instead of closing this question with something that hardly has anything to do with it.

Maarten Dhondt
  • 577
  • 1
  • 9
  • 22
  • 1
    Possible duplicate of [Best implementation for hashCode method](http://stackoverflow.com/questions/113511/best-implementation-for-hashcode-method) – roeygol Feb 08 '17 at 10:59
  • Is there an implicit "Objects that are not equal must not have the same UUID"? – Bathsheba Feb 08 '17 at 11:01
  • 1
    @ΦXocę웃Пepeúpaツ I should have specified: I will obviously override the equals methods. That's not the issue here. The question is how I can generate UUIDs. – Maarten Dhondt Feb 08 '17 at 11:01
  • 1
    @roeygol Unless you suggest generating the UUIDs based on hashCodes, I hardly think these are duplicate questions. – Maarten Dhondt Feb 08 '17 at 11:01
  • @Bathsheba Yes, there is. With high probability that is. – Maarten Dhondt Feb 08 '17 at 11:02
  • No indeed they are not. I'm asking you to clarify if ""Objects that are not equal must not have the same UUID" must also hold. – Bathsheba Feb 08 '17 at 11:03
  • So the `UUID` is based on the content of the `Object`? Why bother? Why not just use the content of the `Object` for the `equals`? – Boris the Spider Feb 08 '17 at 11:03
  • @BoristheSpider because these will be generated on different machines. One machine can not access the object on the other machine. But they should generate the same UUIDs – Maarten Dhondt Feb 08 '17 at 11:04
  • @MaartenDhondt that I understood. But let's say that your `Object` is `Person` and equality is defined as a person with the same `name` (yes, bad idea, whatever). Now, if you generate a UUID from `new Person("Jim")` and then generate a UUID from the `new Person("Jim")` and they must be the same UUID; surely you can use "Jim" as the UUID?! Basically, work out what **exactly** `equals` means in your context and use that. You seem to be looking for some magic way for the computer to work out `equals` semantics for your domain - sadly no such magic exists. – Boris the Spider Feb 08 '17 at 11:06
  • @BoristheSpider the reason I am not using the fields (that matter for equality) directly is because my objects have dozens of fields and concatenating them to create a uuid will result in a String that's way too long. Hashing such a string might be the solution I am hoping for. But that's the second part of my question. If I want to use `nameUUIDFromBytes`, do I give it `String.getBytes()` as input? What about namespaces the `nameUUIDFromBytes` claims to use? – Maarten Dhondt Feb 08 '17 at 11:16
  • @MaartenDhondt you can examine the source code thyself, there's no namespaces, just MD5 of byte[] input. – Alexander Yanyshin Feb 08 '17 at 11:25

2 Answers2

1

The UUID that an operating system will generate reserves the right to blend in information from the machine along with the time information &c. (In fact early Microsoft UUID generators would take network card information which was really quite insecure since it was possible to back that out from a generated UUID!).

So using your favourite UUID generator is not appropriate.

What you could do is to essentially enhance the methods used to create a hash code, extending that to 128 bits. Convert that byte array to a UUID format, and you're done.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • There is a [type 3 UUID](https://tools.ietf.org/html/rfc4122#section-4.3) which based on MD5 digest of a user-supplied name and not using any machine specific information. For example, see a source code of `java.util.UUID#nameUUIDFromBytes` method, there nothing except MD5 hashing and repacking of resulting bytes as UUID. So the author of original question definitely can pack all his class fields used in `equals` as byte[] with help of Java serialization or NIO and pass resulting bytes to `nameUUIDFromBytes` to obtain type 3 UUID. – Alexander Yanyshin Feb 08 '17 at 11:22
1

The result will be the same from different machines. It is like hashing them.

By using nameUUIDFromBytes you create a type 3 compliant uuid.

gkatzioura
  • 2,655
  • 2
  • 26
  • 39