【问题标题】:TreeMap putting BigDecimal key with trailing zero after decimal has no effectTreeMap 将 BigDecimal 键放在小数点后尾随零无效
【发布时间】:2017-05-02 05:51:40
【问题描述】:

将值放入 M​​ap 中的键中而不是在键中添加值

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

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

我在课堂上写过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;
        }
    }

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

【问题讨论】:

  • 你觉得3.13.10有什么区别?
  • 如何更改哈希码,以便根据字符串长度 + BigDecimal.hashCode 计算?
  • 从某个可能不是大十进制的位置检索一些值可能是字符串,我必须根据这两个值做出决定,早些时候我尝试过浮点和双精度,但它们不起作用。所以我在帖子中阅读了使用 BigDecimal 进行计算
  • 那是我想要覆盖它但如何? @stackoverflow.com/users/2310289/scary-wombat
  • 为什么您认为需要将BigDecimals 与这些小数的字符串表示形式相关联?

标签: java hashmap bigdecimal treemap


【解决方案1】:

参考TreeMap的Javadoc

请注意,与任何排序图一样,由树状图维护的排序以及是否提供显式比较器,如果该排序图要正确实现 Map 接口,则必须与 equals 保持一致。

由于BigDecimalcompareToequals 不一致(compareTo 可能返回 0 但等于返回 false)。 使用HashMap 代替,考虑hashCodeequals 作为密钥。

参考BigDecimal#equals方法的Javadoc

将此 BigDecimal 与指定的 Object 进行比较是否相等。与 compareTo 不同,此方法仅当两个 BigDecimal 对象的值和比例相等时才认为它们相等(因此,通过此方法进行比较时,2.0 不等于 2.00)。

当我们执行以下代码时

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 具有相同的值和比例,因此它们被认为是相同的 Object。

然后我们用下面的代码比较不同比例的 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());

【讨论】:

  • 这一切都是对的,但这无关紧要,因为 TreeMap 不使用 hashCode 和 equals。
  • @stackoverflow.com/users/571407/jb-nizet 所以我无法在我的班级中实现对 hashCode() 的覆盖
  • 如果你尝试第二段代码,你会发现没有必要覆盖哈希码。通常只有自定义创建的类才需要覆盖哈希码方法。另外,覆盖应该在你用于key(BigDecimal)的类上完成。覆盖BigDecimalMap的hashCode。将没有效果。
【解决方案2】:

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),所以在第二次插入后,映射中的值被替换。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-02
    • 1970-01-01
    相关资源
    最近更新 更多