Search code examples
javahashmapbigdecimaltreemap

TreeMap putting BigDecimal key with trailing zero after decimal has no effect


Putting value in key in Map not adding value in key

public static void putKey() {
    TreeMap<BigDecimal,String> trmap = new TreeMap<BigDecimal,String>();
    MathContext mc = new MathContext(2);
    BigDecimal b1 = new BigDecimal(3.1,mc);
    BigDecimal b2 = new BigDecimal(3.10,mc);
    BigDecimal b3 = new BigDecimal(3.2,mc);
    BigDecimal b4 = new BigDecimal(3.3,mc);
    BigDecimal b5 = new BigDecimal(3.4,mc);
    
    trmap.put(b1, "3.1");
    trmap.put(b2, "3.10");
    trmap.put(b3, "3.2");
    trmap.put(b4, "3.3");
    trmap.put(b5, "3.4");
    
    System.out.println(trmap);
}

in the above map 3.10 is not added in the key.

so I have tried to compute the hash code for both values

public static void putKey() {
    TreeMap<BigDecimal, String> trmap = new TreeMap<BigDecimal, String>();
    MathContext mc = new MathContext(2);
    BigDecimal b1 = new BigDecimal(3.1, mc);
    BigDecimal b2 = new BigDecimal(3.10, mc);
    BigDecimal b3 = new BigDecimal(3.2, mc);
    BigDecimal b4 = new BigDecimal(3.3, mc);
    BigDecimal b5 = new BigDecimal(3.4, mc);

    trmap.put(b1, "3.1");
    trmap.put(b2, "3.10");
    trmap.put(b3, "3.2");
    trmap.put(b4, "3.3");
    trmap.put(b5, "3.4");

    System.out.println(trmap);
    int hashcodeb1 = b1.hashCode();
    int hashcodeb2 = b2.hashCode();

    System.out.println("3.1-->" + hashcodeb1);
    System.out.println("3.10-->" + hashcodeb2);
}

both hash code are computing the same value my requirement is that I want to put both both values in my map, So with some help of other forum post it looks like I have to override hashCode() method but it returns int as value and I am not sure it will help in my case.

I have written hashCode() in my class

public class BigDecimalMap {
    public BigDecimalMap() {
        super();
    }

    public static void main(String[] args) {
        BigDecimalMap bigDecimalMap = new BigDecimalMap();
        putKey();
        }
    
        public static void putKey() {
            TreeMap<BigDecimal, String> trmap = new TreeMap<BigDecimal, String>();
            MathContext mc = new MathContext(2);
            BigDecimal b1 = new BigDecimal(3.1, mc);
            BigDecimal b2 = new BigDecimal(3.10, mc);
            BigDecimal b3 = new BigDecimal(3.2, mc);
            BigDecimal b4 = new BigDecimal(3.3, mc);
            BigDecimal b5 = new BigDecimal(3.4, mc);
    
            trmap.put(b1, "3.1");
            trmap.put(b2, "3.10");
            trmap.put(b3, "3.2");
            trmap.put(b4, "3.3");
            trmap.put(b5, "3.4");
    
            System.out.println(trmap);
            int hashcodeb1 = b1.hashCode();
            int hashcodeb2 = b2.hashCode();
    
            System.out.println("3.1-->" + hashcodeb1);
            System.out.println("3.10-->" + hashcodeb2);
        }
        
        public int hashCode() {
            return 1;
        }
    }

Please help in identifying how to add both values.


Solution

  • Refer to Javadoc of TreeMap

    Note that the ordering maintained by a tree map, like any sorted map, and whether or not an explicit comparator is provided, must be consistent with equals if this sorted map is to correctly implement the Map interface.

    Since compareTo of BigDecimal is not consistent to equals(compareTo may return 0 but equals return false). Use HashMap instead which consider hashCode and equals for the key.

    Refer to Javadoc of BigDecimal#equals method

    Compares this BigDecimal with the specified Object for equality. Unlike compareTo, this method considers two BigDecimal objects equal only if they are equal in value and scale (thus 2.0 is not equal to 2.00 when compared by this method).

    As we execute the following code

    MathContext mc = new MathContext(2);
    BigDecimal b1 = new BigDecimal(3.1, mc);
    BigDecimal b2 = new BigDecimal(3.10, mc);
    System.out.println(b1.doubleValue());
    System.out.println(b2.doubleValue());
    System.out.println(b1.scale());
    System.out.println(b2.scale());
    System.out.println(b1.compareTo(b2));
    System.out.println(b1.equals(b2));
    System.out.println(b1.hashCode());
    System.out.println(b2.hashCode());
    

    Since b1 and b2 has same value and scale, they are considered to be same Object.

    Then we compare b1 and b2 with different scale with below code. Inorder to create BigDeciaml with different scale, use the constructor with String instead of double(refer to the note https://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html#BigDecimal(double)).

    BigDecimal b1 = new BigDecimal("3.1");
    BigDecimal b2 = new BigDecimal("3.10");
    System.out.println(b1.doubleValue());
    System.out.println(b2.doubleValue());
    System.out.println(b1.scale());
    System.out.println(b2.scale());
    System.out.println(b1.compareTo(b2));
    System.out.println(b1.equals(b2));
    System.out.println(b1.hashCode());
    System.out.println(b2.hashCode());