TreeMap 在小数点后放置带尾随零的 BigDecimal 键无效

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

在 Map 中将值放入键中而不是在键中添加值

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);
}

上图3.10中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);
    int hashcodeb1 = b1.hashCode();
    int hashcodeb2 = b2.hashCode();

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

两个哈希码都在计算相同的值我的要求是我想把两个值都放在我的地图中,所以在其他论坛的帮助下 post 看起来我必须覆盖 hashCode() 方法,但它 returns int 作为值,我不确定它对我的情况是否有帮助。

我在class

中写了hashCode()
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;
        }
    }

请帮助确定如何将这两个值相加。

参考TreeMap

的Javadoc

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.

因为 BigDecimalcompareToequals 不一致(compareTo 可能 return 0 但等于 return false)。 使用 HashMap 而不是考虑 hashCodeequals 作为键。

参考BigDecimal#equals方法的Javadoc

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).

当我们执行下面的代码时

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());

由于 b1 和 b2 具有相同的值和比例,因此它们被认为是相同的对象。

然后我们用下面的代码比较不同比例的b1和b2。 为了创建具有不同比例的 BigDeciaml,使用带有 String 而不是 double 的构造函数(参考注释 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());

A Treemap 实现为红黑树;一个关心 compareTo 是如何实现的,因为它必须将您的条目移动到 leftright

所以 TreeMap 只关心你的键如何实现 compareTo 方法。现在,如果您查看这段代码:

    BigDecimal b1 = new BigDecimal("3.1");
    BigDecimal b2 = new BigDecimal("3.10");

    System.out.println(b1.compareTo(b2)); // this prints zero since
                        // they are the same according to compareTo

    TreeMap<BigDecimal, String> map = new TreeMap<>();
    map.put(b1, "aaa");
    map.put(b2, "bbb");

    System.out.println(map); // {3.1=bbb}

注意最后,在两次插入之后,TreeMap 中只有一个条目。发生这种情况是因为 b1b2 相同(根据 compareTo),因此在第二次插入后该值在映射中被替换。