Thursday, June 25, 2026

Always compare objects (including Integer and Long etc) with equals

 The difference between equals() and == in Java is known to everyone. There is a minute detail, though, which I will explain a moment later.

Consider the situation:

Map<String, Integer> map = new HashMap<>();
map.put("a",128);
map.put("b",128);

map.put("c",1100);
map.put("d",1100);

map.put("e",5);
map.put("f",5);

System.out.println(map.get("a") == map.get("b"));
System.out.println(map.get("c") == map.get("d"));
System.out.println(map.get("e") == map.get("f"));

The first two return false, while the third one returns true.
This means that if you depend on ==  for equality comparison of two wrapper objects, your code can silently fail.

Why do you need to compare?
Various reasons based on your requirement. One common reason could be using them in a Comparator. Whatever be the reason, using == can fail you and your code.

Why does it fails? 
JVM caches primitives to some extent. For example, int and long values -128 to 127 are cached. The range is decided by the writers of JLS (Java Language Specification) to improve performance by avoiding repeated creation and garbage collection of objects for common use cases such as loops, basic counts or array indexing. Similarly, the booleans true and false are cached too.

When you use java.lang.Integer, or do boxing such as in the map values above, new Object is created which resides on the heap. Comparing them means comparing object. If the value falls within the cached values, JVM object simply references or points to the cache object.
So when you have Integer a = 128; JVM creates a new Object on the heap. When you have Integer b = 120, JVM find the value in the cache and just points to that, preventing a new Object to be managed.
When you use primitives, int a = 128, this is just a member of the thread stack or sits inside the object of the class where its defined. 

Now see below:
Integer a = 130, b = 130;
System.out.println(a==b); // false
System.out.println(a==130); // true

First one gives false since objects are compared, and both are different by virtue of their hashcodes even if their content is same.
Second line gives true because upon seeing the ==, JVM just unboxes the "a" to primitive 130 and quickly compares.

An actual code:

Map<String, Integer> map = new HashMap<>();
map.put("a", 130);
map.put("b", 120);
map.put("c", 130);
map.put("e", 140);
map.put("f", 150);

        List<String> sortedList = new ArrayList<>();
sortedList.addAll(map.keySet());
Comparator<Integer> comparator = (str1, str2) -> {
// reverse sort on same values
if(map.get(str1) == map.get(str2)) {
return str2.compareTo(str1);
}
// normal sort on different values
return Integer.compare(map.get(str1), map.get(str2));
};
        Collections.sort(sortedList, comparator);

The expectation is that the list should be sorted based on the below conditions:
1. If count is the same for multiple strings, sort them in reverse order
2. If the counts of two strings are not same, sort them in a normal ascending or lexicographical order.

Our expected output should be : [b, c, a, e, f].
Notice how "a" and "c" are in reverse order.

But if you run the above code, you will get: [b, a, c, e, f].
"a" and "c" never were reverse sorted because the == actually compared two different objects with different hash code, ensuring our goal was not met. 
Were we having some other strings with the same count within the cache-able range, i.e. -128 to 127, this == would have worked flawlessly.
This means our code is now flaky with == comparison of two Objects. Only way it will work as expected is to use equals():

            if(map.get(str1).equals(map.get(str2))) {
return str2.compareTo(str1);
}
On paper and IDE, == looked safe until it silently failed.

Conclusion:
The most important thing to remember is not to depend on things that confuse or feel flaky, strictly use whats advised: == for primitives and .equals for objects (wrapper classes like Integer, Long are objects after all).

Thursday, October 25, 2018

Git: Resolve Conflicts in PR

What to do when GitHub does not allows you to merge a Pull Request due to conflicts!
First of all, rebase often to avoid this problem in most cases.
Sharing bits from my experience. The solutions that worked for me are:

1. git rebase

The best way is to do it locally using terminal or command prompt. Lets say you raised a PR from origin/develop to upstream/develop branch and got conflict. Go to your command prompt, rebase master onto develop and push to develop branch. PR should get resolved.
But this won’t work when the tips are just big time outdated.

Wednesday, August 16, 2017

Using Wiremock for quick and easy http mocks of your API

I published this article at the turn of the year in my company's internal blog. I am republishing it here thinking it might be useful to outside world who are looking at a concise guide.

WireMock is an HTTP mock server. At its core it is web server that can be primed to
  1. serve canned responses to particular requests (stubbing) and 
  2. that captures incoming requests so that they can be checked later (verification).
Imagine your application component is dependent on some other component for development or testing, here WireMock can come in and remove your dependency headaches.
You can agree the contract, design the stub and use it for your own component without tight integration with other component. This makes the development and testing much
easier and faster.

Monday, February 20, 2017

Stackoverflow Documentation | The way to go

Many months now, the Stackoverflow documentation is maturing with new examples and continuous edits to existing examples. It covers many programming languages, and should be on top of your TO-DOs if you are trying to broaden your skill set or even validate what you already have in your kitty.

If you feel it's good, you should consider making it awesome for others. Ultimately, giving back to the community only makes sure of technology's global reach and rapid development. Click here: http://stackoverflow.com/documentation.

Thursday, September 1, 2016

Recursion is all about trust.

Image credit: http://www.cr31.co.uk/logoarts/
The secret of recursion is only one thing. Trust. Here's a neat example to show you what it exactly means. Quoting Stephan van Hulst from Code Ranch here.

Say there's a long queue of people, and you want to know how many are in the queue. You can simply ask the guy in front of you how many people there are in the queue, and then add 1 for yourself. You don't care how the guy in front of you got the answer, you just trust that it's correct. The guy in front uses the same technique. This goes on all the way until the guy at the front of the queue is asked how many people there are in the queue. The guy at the front sees no people in front of him, so he just reports 1. He is the base case.

final class PersonInQueue {
 
  private final PersonInQueue next;
 
  int askForLengthOfQueue() {
    if (next == null)
      return 1;
 
    return next.askForLengthOfQueue() +1;
  }
}
Here's the post: Algorithm explanation if you want to have a look. The question was on Tower of Hanoi.

Sunday, April 10, 2016

IP v4 address matcher (regex)

IP address is a string in the form "A.B.C.D", where the value of A, B, C, and D may range from 0 to 255. Leading zeros are allowed. The length of A, B, C, or D can't be greater than 3.

image
The pattern is: ^(?:(?:25[0-5]?|2[0-4]?[0-9]?|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]?|2[0-4]?[0-9]?|[01]?[0-9][0-9]?)$

Java:
public class IPv4Regex {
	static final String ipV4Pattern = "^(?:(?:25[0-5]?|2[0-4]?[0-9]?|[01]?[0-9][0-9]?)\\.){3}"
			+ "(?:25[0-5]?|2[0-4]?[0-9]?|[01]?[0-9][0-9]?)$";
	
	public static void main(String[] args) {
		System.out.println("000.123.234.245".matches(ipV4Pattern));
	}
}

Tuesday, March 8, 2016

Tree traversal notes

1. Inorder:

- travel left subtree in inorder
- visit root
- travel right subtree in inorder

Recursive approach:

void inOrder() {
 if(root != null) {
  inOrder(root.left);
  System.out.println(root.data);
  inOrder(root.right);
 }
}

Iterative approach using stacks:

void inOrder() {

    Stack stack = new Stack();

    Node current = root;

    while(current!=null || !stack.isEmpty()) {
        //push to stack and move to left sub-tree
        if(current!=null){
            stack.push(current);
            current = current.left;
        }
        else { //we need to pop out nodes from stack and shift to its right sub-tree
            current = stack.pop(); //visited node
            System.out.println(current.data);
            current = current.right;
        }
    }
}

2. Pre-order:

- visit root
- travel left subtree in preorder
- travel right subtree in preorder

Recursive approach:

void preOrder() {
    if(root != null) {
        System.out.println(root.data);
        preOrder(root.left);
        preOrder(root.right);
    }
}

Iterative approach using stacks:

void inOrder() {

    Stack stack = new Stack();

    Node current = root;

    while(current!=null || !stack.isEmpty()) {
        //print each value, then push its right subtree to stack and move to left subtree
        if(current!=null){
            System.out.println(current.data); //visited node
            stack.push(current.right); //push right subtree
            current = current.left; //shift to left subtree
        }
        else {
            current = stack.pop();
        }
    }
}

Friday, February 12, 2016

Designing your own iterable stuff

Or, simply, implementing iterator logic in your own class, on which you can iterate or even use for-each loop. Because, for-each works only on Iterator based collections.
Following is a generic Java 7 code that takes into account a simple custom linked list implementation that is generic and can be iterated over, using following steps.
1. The stuff we want to iterate upon has to be Iterable and expose
iterator()
2. Design a java.util.Iterator by overriding hasNext(), next() and remove().

Sunday, June 28, 2015

Sorting Key-Value pairs in Java

Saw making your own sorting logic by implementing Comparable or Comparator? If not, click here. Now, how about sorting key-value pairs! Well, we need just a little code modification. See following code sample that sorts key-value pairs, first by key, then values. Look at the compareTo method implementation.

Sunday, June 7, 2015

Comparable and Comparator- When and how to use? [Concise]

When there comes the need of sorting objects, be it using Collections.sort() or just adding elements to Treeset etc, java.lang.Comparable and java.util.Comparator come into picture. For default sorting of objects in the collection, we need to implement Comparable and override below method in that class, unless we are using some pre-defined class that already implements Comparable like String, Integer etc.,
int compareTo(T o)
If we want to provide an external sorting logic to override the default one, the class needs to implement Comparator interface and override the following method:
int compare(T o1, T o2)
The question: Why use Comparator when we already have Comparable?
Answer: If you have authored that class, then you can give a default sorting behavior by implementing Comparable and use that logic to sort whenever needed. Now, let's say that you are using an existing class whose source you can not modify and the default sorting logic of which you are not satisfied with. What now? Just write a Comparator using your own sorting process and use that instance to sort. See below sample programs.

The API information is here:
1. java.lang.Comparable
2. Java.util.Comparator
Lets dig into this with our custom class.

Thursday, January 29, 2015

native2ascii - Native-to-ASCII Converter in Java

This utility converts a file with characters in any supported character encoding to one with ASCII and/or Unicode escapes, or visa versa.

You already have this tool if you have JDK. It is present in your JDK installation bin folder. Its recommended to add JAVA_HOME to your PATH environment variable for access of java tools throughout your machine.

Saturday, December 20, 2014

Falling in love with InteliJ Idea Community IDE

The local file history that keeps a track on my changes to a file, I am all smiles now! :~)

Local History - Click on the image to enlarge

Tuesday, May 20, 2014

Java Map/Collections Cheat Sheet : Simply 'When and What to use'?

This is a notoriously simple when and what to use Java collection API cheat sheet, containing most common implementations.

Monday, May 19, 2014

Find the occurrence of words in a given string

IDEONE: http://ideone.com/9SENHc
package com.learning.collection;
import java.util.*;
/**
 * Count frequency of words occurring in a string
 */
public class MapExample {
    public static void main(String[] args){
        String str = "ika pika ting tong ting tong me";
        String[] strr = str.split("\\s");
        workMap(strr);
    }

    static void workMap(String...words){
        Map map = new HashMap();
        Integer ONE = new Integer(1);

        for(String word : words){
            Integer frequency = (Integer)map.get(word);
            /*
            'frequency' is the count of the words.
            For a new word getting added to the Map, we set its frequency as 1.
            For existing words, we take their existing frequency (value in the map)
            and increment it and put back into the map correspondint to that word (key in the map)
             */
            frequency = (frequency == null) ? ONE : new Integer(frequency.intValue() + 1);
            map.put(word, frequency);
        }
        System.out.println("Unsorted:");
        System.out.println(map);

        Map sortedMap = new TreeMap(map);
        System.out.println("Sorted:");
        System.out.println(sortedMap);
    }
}
Output:
Unsorted: {ika=1, pika=1, ting=2, tong=2, me=1}
Sorted: {ika=1, me=1, pika=1, ting=2, tong=2}


--Suggestion by Dr. Heinz Kabutz (Java Champion)
How you would count words in Java 8 :-) And if you want to do it in parallel, just add parallel() into the stream...
import java.util.*;
import java.util.function.*;
import java.util.stream.*;

public class MapExample {
  public static void main(String[] args) {
    String str = "hello world how are you how is life i am into ascent";

    Map<String, Integer> map = Arrays.stream(str.split("\\s"))
        .collect(Collectors.toMap(
            Function.identity(),
            n -> 1,
            (n1, n2) -> n1 + n2,
            TreeMap::new));
    System.out.println("map = " + map);
  }
}

Wednesday, April 30, 2014

Finding the JAR files which contain a specific .class file on Linux machine

This program searches through all .jar files in the current directory, and in any sub-directories, looking for the class that you specify. This can be very handy if you need to use a class in a Java program, but aren't sure which .jar file contains it.

Logic of script: The key is to get a list of all the jar files in present directory, open each jar archive and search it with our input classname, and for all positive output, print the name of the jar file on screen.

Thursday, April 24, 2014

Synchronization in Java : class and object locking concept

People talk about two types of multi-threaded locking - object and class. In my knowledge, locking is done on objects only. Let me explain.

Case 1: On objects we create using new or factory methods etc.
void synchronized myMethod(Type param) {
  //will lock on the instance used to call this method
}
or
synchronized(this) {
 //will lock on current object
}
or
synchronized(obj1) {
 //will lock on specified obj1 object
}

Monday, April 21, 2014

Writing singleton classes in Java

Singleton classes are those classes which can be instantiated only once. We need to restrict the creation of multiple instances of that class by blocking constructor access using new keyword etc, and instead regulate the incoming instance requests by creating the instance only once and return the same instance time and again on multiple calls.
Where do we actually need this singleton design pattern?

Friday, April 11, 2014

Bubble Sorting in Java

Bubble sorting sorts the array in-place bubbling up the largest value.
Complexity:
Worst case - O(n^2); average case - O(n^2); best case - O(n)

Visualization: (src. Wiki)

Thursday, March 20, 2014

Fibonacci Series in Java


Q. Print Fibonacci series in Java.
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55
public class FibonacciSeries {
  
 public static void main(String[] args) {
  int sum = 0;
  //how many numbers to print
  for(int i=0, j=1; i<=10; i++){
   if(i==0){
    //for printing first number which is 0
    System.out.print(0 + ", ");
   }
   else{
    //j has last 'sum', and sum now stores latest added value
    //while the control enters again, j gets latest 'sum' value before
    //new sum is calculated and printed again
    sum = j + (j=sum);
    System.out.print(sum + ", ");
   }
  }
 }
}

Thursday, January 30, 2014

Matrix Multiplication in Java


package com.learning.ds.matrices;
import com.learning.ds.arrays.ArrayUtil;

/**
 * Created by Rajdeep on 28/1/14.
 */
public class MatrixMultiplicationDemo {
    public static void main(String[] args){
        //the temp1 and temp2 array values can be changed to test this program
        int[][] temp1 = {{2,0}};
        int[][] temp2 = {{1,1,1}, {2,2,2}};

        System.out.println("Matrix 1: ");
        ArrayUtil.print2DIntArray(temp1);
        System.out.println("Matrix 2: ");
        ArrayUtil.print2DIntArray(temp2);

        if( !( isFilledMatrix(temp1) && isFilledMatrix(temp2) ) ){
            System.out.println("One of the matrices is not filled completely and can't be used for multiplication.");
        }
        else{
            //check dimension
            if(!areMatricesMultipliable(temp1, temp2)){
                System.out.println("The number of columns in first matrix is unequal to number of rows in second matrix. The must be equal for dot product.");
            }
            else{
                System.out.println("can be multiplied");
                int[][] tempNew = multiplyMatrices(temp1, temp2);
                System.out.println("new matrix is: ");
                ArrayUtil.print2DIntArray(tempNew);
            }
        }
    }

    private static int[][] multiplyMatrices(int[][] temp1, int[][] temp2) {
        //
        int rowCount1 = temp1.length;
        int colCount1 = temp1[0].length;
        int colCount2 = temp2[0].length;

        int[][] tempNew = new int[rowCount1][colCount2];

        for(int i=0; i < rowCount1; i++){
            int k=0;
            while(k < colCount2){
                int tempVal = 0;
                for (int j=0; j < colCount1; j++){
                    tempVal = tempVal + ( temp1[i][j] * temp2[j][k] );
                }
                tempNew[i][k] = tempVal;
                k++;
            }

        }

        return tempNew;
    }

    //matrix multiplication rule is
    //no of columns of left matrix == no of rows in right matrix
    // (m x n) . (n x p) = (m x p)
    private static boolean areMatricesMultipliable(int[][] mat1, int[][] mat2){
        return (mat1[0].length == mat2.length);
    }

    //check the matrix has all elements filled or not
    //In other words, checking whether number of columns in each row is same
    private static boolean isFilledMatrix(int[][] mat){
        boolean retVal = false;
        int rows = mat.length;
        
        if(rows == 1){
            retVal = true;
        }
        else {
            for(int i=0; i < (rows-1); i++){
                if(mat[i].length != mat[i+1].length){
                    retVal = false;
                    break;
                }
                else
                    retVal = true;
            }
        }

        return retVal;
    }
}


The
ArrayUtil.print2DArray(int[][] args)
prints the array on screen through normal 'for' loops.
One sample output:
Matrix 1:
2 0
Matrix 2:
1 1 1
2 2 2
can be multiplied
new matrix is:
2 2 2
Another sample output by changing the temp1 and temp2 arrays in main() method:
Matrix 1::
2 0 3:
Matrix 2::
1 1 1:
2 2 2:
One of the matrices is not filled completely and can't be used for multiplication.