Overriding equals and hashCode vs providing only Single Instance on immutable Objects Let's say we have a class SomeInt which holds just one single final int value:

public class SomeInt
{
    private final int value;

    public SomeInt(int value)
    {
        this.value = value;
    }

    public int getValue()
    {
        return this.value;
    }
}


Option A - Overring equals and hashCode:

public class SomeInt
{
    private final int value;

    public SomeInt(int value)
    {
        this.value = value;
    }

    public int getValue()
    {
        return this.value;
    }

    @Override
    public boolean equals(Object other)
    {
        if (!(other instanceof SomeInt))
        {
            return false;
        }

        return ((SomeInt) other).hashCode() == hashCode();
    }

    @Override
    public int hashCode()
    {
        return this.value;
    }
}


Option B - Providing only one Instance per Value:

import java.util.Map;
import java.util.HashMap;
import java.lang.ref.WeakReference;

public class SomeInt
{
    private static final Map&lt;Integer, WeakReference&lt;SomeInt&gt;&gt; INSTANCES = new HashMap&lt;&gt;();
    private final int value;

    private SomeInt(int value)
    {
        this.value = value;
    }

    public synchronized static SomeInt of(int value)
    {
        WeakReference&lt;SomeInt&gt; weakRef = INSTANCES.get(value);
        SomeInt instance = null;

        if (weakRef != null)
        {
            // keep reference before asking isEnqueued to ensure
            // it's not getting garbage collectedbetween the calls
            instance = weakRef.get();
        }

        if (weakRef == null || instance == null || weakRef.isEnqueued())
        {
            instance = new SomeInt(value);
            INSTANCES.put(value, new WeakReference&lt;&gt;(instance));
        }

        return instance;
    }

    public int getValue()
    {
        return this.value;
    }
}


Pros of A:


If the Object holds references to other Complex-Types the implementation is much easier and will be easy to customize when something changes
Can also be used with mutable Objects


Cons of A:


There may be many Objects with the same information


Pros of B:


There will always be only one Object holding this information
== comparison possible since equality is guaranteed by the generating method


Cons of B:


Can only be used with immutable Objects


Question:
What is the better approach to ensure comparisons and occurences in Maps and Collections don't fail?
Your approach is flawed in both ways. I see some fundamental misunderstanding of equals, hashcode and == operator.

To Option A


  Pros of A ... Can also be used with mutable Objects


Overriding hashcode and equals on mutable objects will lead to unaccessable elements within hash-based datastructures like HashMap or HashSet. Always make sure your objects are immutable when overriding these methods.

Furthermore your implementation of equals is semantically wrong. This is because you make "equals" dependent on hashcode only.

Maybe you can precheck the hashcode to avoid a complex equals-evaluation if the hashcodes aren't equal.

hashcode has a totally other purpose. It provides a value that is used in hash-based datastructures to balance lookup tables to increase lookup performance and minimze the binary search path.

You may say that Integer.hashcode(int i) always returns i. Yes, but you depend on implementation details for a totally different semantic.

A correct implementation for your SomeInt:

public class SomeInt {

    private final int value;

    public SomeInt(int value) {
        this.value = value;
    }

    public int getValue() {
        return this.value;
    }

    @Override
    public boolean equals(Object object) {

        boolean equals = false;

        if (object instanceof SomeInt) {

            SomeInt that = (SomeInt) object;

            equals = this.value == that.value;


        }

        return equals;
    }

    @Override
    public int hashCode() {
        return this.value;
    }

}


To Option B

Yes you can do so. But the achieve the same with the correct hashcode equals implementation on immutable datastructures with less overhead.

Logical path


If you override equals you have to override hashcode
hashcode is used within hash-based datastructures to put objects into  buckets
If you change the value hashcode depends on AND you have put the object into a hash-based datastructure before, it is very probable that you never find this object again.
Therefore values that are used to generate the hashcode must not change if you want to use the objects within hash-based datastructures.