Java SE 5 introduced the concept of autoboxing.
Integer i1 = 1000;
Integer i2 = 1000;
assert (i1 != i2); // i1 and i2 are *not* the same object ---true
assert (i1.equals(i2)); true
Is equivalent to
Integer i1 = new Integer(1000);
Integer i2 = new Integer(1000);
assert (i1 != i2); true
assert (i1.equals(i2));true
So i1 holds an object of type Integer (as opposed to a primitive int value). When you create two *new* objects then they will always be non-identical (!=) even though the data within the objects *is* the same (equals). This is the major difference between the == operator and the equals() method; the == operator determines object identity (same object reference).
However, for numbers under a certain value (I think under 128) this equivalency is *not* true. For example...
Integer i1 = 10;
Integer i2 = 10;
assert (i1 == i2); // i1 and i2 are the same object true
assert (i1.equals(i2)); true
So, the object referred to by i1 is identical to the object referred to by i2. Why does this happen? It turns out that the Java compiler performs an optimization for "creating" Integer objects (using autoboxing) for small numeric values. The compiler has an object cache of the first 128 integer values and it will always reuse the same Integer object when autoboxing the same int value.