20

I made a vector set in order to avoid thrashing the GC with iterator allocations and the like ( you get a new/free each for both the set reference and the set iterator for each traversal of a HashSet's values or keys )

anyway supposedly the Object.hashCode() method is a unique id per object. (would fail for a 64 bit version?)

But in any case it is overridable and therefore not guaranteed unique, nor unique per object instance.

If I want to create an "ObjectSet" how do I get a guaranteed unique ID for each instance of an object??

I just found this: which answers it.

How to get the unique ID of an object which overrides hashCode()?

Community
  • 1
  • 1
peterk
  • 5,136
  • 6
  • 33
  • 47
  • 1
    The question is not clear. What exactly you're trying to acheive and why does it need a unique ID per object? – Paolo Jan 20 '12 at 08:26
  • 1
    The description of what you're trying to do is *really* vague. Could you give more information? There may well be a better way of achieving your bigger aim. – Jon Skeet Jan 20 '12 at 08:27
  • I saw this answer/questin which answers what I wanted. http://stackoverflow.com/questions/909843/java-how-to-get-the-unique-id-of-an-object-which-overrides-hashcode – peterk Jan 20 '12 at 18:18
  • @JonSkeet to create a container which is a set, that will contain exactly one instance of each object that is not a HashMap but relys on a comparable value unique to each object. And do this without relying on an overridable interface/method such as Comparable<> or hashCode(). – peterk Jan 20 '12 at 18:22
  • @BjörnPollex right I found the duplicate - it didnt show up on my initial search. – peterk Jan 20 '12 at 18:25
  • @peterk: Then `IdentityHashMap` sounds like it's what you're after. – Jon Skeet Jan 20 '12 at 18:27
  • @JonSkeet I meant every instance even if hashCode() returns a result that is the same for multiple objects. – peterk Jan 20 '12 at 18:29
  • 1
    @peterk: Yes, I know. Did you read the documentation for `IdentityHashMap`? – Jon Skeet Jan 20 '12 at 18:31
  • It should be noted that `System.identityHashCode(Object)` from the selected answer may be not distinct for distinct objects (as already stated in other answers and comments)! https://stackoverflow.com/a/8939049/4130619 seems to be the correct answer – reducing activity Jul 24 '19 at 15:25

4 Answers4

45

The simplest solution is to add a field to the object. This is the fastest and most efficient solution and avoid any issues of objects failing to be cleaned up.

abstract Ided {
    static final AtomicLong NEXT_ID = new AtomicLong(0);
    final long id = NEXT_ID.getAndIncrement();

    public long getId() {
         return id;
    }
}

If you can't modify the class, you can use an IdentityHashMap like @glowcoder's deleted solution.

private static final Map<Object, Long> registry = new IdentityHashMap<Object, Long>();
private static long nextId = 0;

public static long idFor(Object o) {
    Long l = registry.get(o);
    if (l == null)
        registry.put(o, l = nextId++);
    return l;
}

public static void remove(Object o) {
    registry.remove(o);
}
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • will the code above where you add a field to the object guarantee a unique id per instance created in the face of objects created from multiple threads simultaneously? – Geek Mar 21 '14 at 04:42
  • 1
    @Geek It will if you use an AtomicLong. – Peter Lawrey Mar 23 '14 at 07:31
9

No, that's not how hashCode() works. The returned value does not have to be unique. The exact contract is spelled out in the documentation.

Also,

supposedly the Object.hashCode() method is a unique id per object

is not true. To quote the documentation:

As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects.

NPE
  • 486,780
  • 108
  • 951
  • 1,012
6

java.lang.System.identityHashCode(obj); will do this for you, if you really need it and understand the repercussions. It gets the identity hashcode, even if the method to provide the hashcode has been overridden.

Chris Dennett
  • 22,412
  • 8
  • 58
  • 84
  • 20
    Even if this is already some months old, it should be noted that `System.identityHashCode(Object)` does **not** need to be distinct for distinct objects (as already stated in other answers and comments)! – siegi Apr 26 '12 at 20:06
  • 1
    Solution given there (with some explanations and details) : http://stackoverflow.com/questions/909843/java-how-to-get-the-unique-id-of-an-object-which-overrides-hashcode – Benj Apr 18 '13 at 21:01
  • identityHashCode() returns the result of the hashCode() method defined in Object. in the javadoc for such method it states: "As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects. (This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the JavaTM programming language.)" – Roberto Attias Dec 16 '16 at 01:53
  • unfortunately this is a bit vague. On a 64bit machine, the virtual address space is potentially larger than an int so, if unlikely, it is possible for two objects to have the same value. – Roberto Attias Dec 16 '16 at 01:53
  • I've just fallen over this, or rather, one of my users has. Calling identityHashCode() for several million objects, there are about 8 that have duplicate hash codes. – Michael Kay Feb 23 '23 at 12:35
2

Trying to outperform the java GC sounds like premature optimization to me.

The GC is already tuned to handle small short-lived objects. If you have performance issues with GC, you ought to help the GC, not re-implement it (IMNSHO)

Rolf Rander
  • 3,221
  • 20
  • 21
  • 2
    I would love it if a realtime deterministic GC was available as a plugin for generic java VMs where I could guarantee the GC would consume more more than 2 milliseconds in each frame of a 60hz simulation loop. Reducing allocations and free reduces the inevitable number of periodic GC stalls. – peterk Jan 20 '12 at 18:34