Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Comparing the wrapper types in Java

I have two java.util.List as follows.

List<Long> items = new ArrayList<Long>(){{
   add(141L);
   add(142L);           
}};

List<Long> itemsExist = new ArrayList<Long>(){{
    add(123L);
    add(124L);
    add(125L);
    add(126L);
    add(127L);
    add(141L);
    add(142L);            
}};

I was trying to remove the elements of the List named items, if they are contained in the List named ItemsExist as follows.

Iterator<Long> itemsIterator = items.iterator();

while(itemsIterator.hasNext())
{
    Long item1=itemsIterator.next();
    Iterator<Long> itemsExistIterator = itemsExist.iterator();

    while(itemsExistIterator.hasNext())
    {               
        Long item2=itemsExistIterator.next();
        if(item1==item2)
        {
            itemsIterator.remove();
        }
    }
}

But the removal of the elements (141 and 142) didn't happen because of this condition if(item1==item2) which actually should have been if(item1.equals(item2)), (I can understand the difference between == and equals()).


This could be emulated by a very simple example as follows.

Long a=new Long(5);
Long b=new Long(5);
System.out.println((a==b)+" : "+a.equals(b));

This returns false and true respectively.


The following example returns true in both comparisons.

Long a=5L;
Long b=5L;
System.out.println((a==b)+" : "+a.equals(b));

In this case, both a and b also appear to be the subject of unboxing which doesn't appear to be the case of the other examples. How?

like image 406
Tiny Avatar asked Jun 11 '26 10:06

Tiny


2 Answers

Here is a part of the source code of java.lang.Long:

           private static class LongCache {
  544           private LongCache(){}
  545   
  546           static final Long cache[] = new Long[-(-128) + 127 + 1];
  547   
  548           static {
  549               for(int i = 0; i < cache.length; i++)
  550                   cache[i] = new Long(i - 128);
  551           }
  552       }

            public static Long valueOf(long l) {
  573           final int offset = 128;
  574           if (l >= -128 && l <= 127) { // will cache
  575               return LongCache.cache[(int)l + offset];
  576           }
  577           return new Long(l);
  578       }

It apears to me that the Long class maintains a cache of Long objects between -128 and 127. So a and b variables in your example points to the same object Long.

like image 164
dcernahoschi Avatar answered Jun 12 '26 22:06

dcernahoschi


Just like String pool java maintains a pool for integer values in the range -128 to +127. A similar question was already answered in this site. Please refer Why does the behavior of the Integer constant pool change at 127?

Just to summarize, if you are assigning an integer in the range of -128 to +127 as a literal, it will be picked up from the integer pool and the same object will be returned every time you use the same literal.

eg,

Integer int1 = 123;
Integer int2 = 123; // Get the same object from integer pool
System.out.println(int1.equals(int2));
System.out.println(int1== int2);

The above code gets you true in both conditions.

If you are creating an object using new operator, a new object will be created everytime and the Integer pool will not come into picture. eg,

Integer int1 = new Integer(123);
Integer int2 = new Integer(123); // Gets you a new object
System.out.println(int1.equals(int2));
System.out.println(int1== int2);

equals methods get you true and == check gets you false. You can get more insights here http://www.devx.com/tips/Tip/42276

like image 35
Devadas Avatar answered Jun 12 '26 23:06

Devadas