2

Why do we say that immutable objects use lazy hash code initialization? For mutable objects too, we can calculate hashcode only when required right causing lazy initialization?

Tck
  • 83
  • 6
  • 1
    Feels like homework. Please search for "lazy initialization" on the web. – markspace Nov 14 '18 at 18:00
  • Check out https://stackoverflow.com/questions/18948990/immutable-objects-and-lazy-initialization – ygor Nov 14 '18 at 18:00
  • @ygor, I have gone through the given post. But it is not clear to me as to why we say hashcode method is lazily initialized for immutable objects. For mutable objects too, we can calculate hashcode only when required right causing lazy initialization? – Tck Nov 14 '18 at 18:15
  • I guess it's just a matter of wording. I don't understand it with "lazy initialization" either. It's more interesting for caching topic. Though when it comes to caching, you can ask whether it's lazy or eager (regardless of the method/value). – Rad Nov 14 '18 at 18:24
  • BTW, I suggest to update the question with the information in the comment. That's quite helpful to understand your question. (A tip, if you can ask a question in one sentence or two, most probably you can google it, though this is not your case) – Rad Nov 14 '18 at 18:27
  • *Why do we say that immutable objects use lazy hash code initialization?*: we don't. Maybe someone said that, but he/she was wrong. Or he/she was talking about specific immutabe objects, not all. A hashCode can be computed eagerly (in the constructor) if the object is immutable, or it can be computed lazily and cached, or it can be recomputed at every invocation of hashCode(). It's a design choice. – JB Nizet Nov 14 '18 at 18:33
  • Thanks you for your answers! I am relieved of this question now. Also, I updated the question adding more clarity to it. – Tck Nov 14 '18 at 18:39
  • If the hashCode is computed and returned, there is no hashCode *initialization*. There would be an initialization if some hashCode field was *initialized* somewhere. But that wouldn't make much sense for mutable objects, since mutating the object would make the initialized hashCode obsolete and incorrect. – JB Nizet Nov 14 '18 at 18:44

2 Answers2

5

For mutable classes, it usually doesn't make much sense to store the hashCode, as you'd have to update it every time the object is modified (or at least nullify it so you can recalculate it next time hashCode() is called).

For immutable classes, it makes a lot of sense to store the hash code - once it's calculated, it will never change (since the object is immutable), and there's no need to keep re-calculating every time hashCode() is called. As a further optimization, we can avoid calculating this value until the first time it's needed (i.e., hashCode() is called) - i.e., use lazy initialization.

There's nothing that prohibits you from doing the same on a mutable object, it's just generally not a very good idea.

Mureinik
  • 297,002
  • 52
  • 306
  • 350
1

The advantage of lazy initialization is that hashcode computation is suspended until it is required. Many objects don't need it at all, so you save some computations. Particularly when you have high hash computations. Look at the example below :

class FinalObject {
    private final int a, b;
    public FinalObject(int value1, int value2) {
        a = value1;
        b = value2;
    }

    // not calculated at the beginning - lazy once required
    private int hashCode;
    @Override
    public int hashCode() {
        int h = hashCode; // read
        if (h == 0) {
            h = a + b;    // calculation
            hashCode = h; // write
        }
        return h;         // return local variable instead of second read
    }
}
Ashouri
  • 906
  • 4
  • 19