【问题标题】:When I use computeIfAbsent to calculate fibonacci numbers, hashmap size() returns incorrect value当我使用 computeIfAbsent 计算斐波那契数时,hashmap size() 返回不正确的值
【发布时间】:2019-05-28 15:48:37
【问题描述】:

我有以下代码:

import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;

public class DynamicFib
{
    private static Map<Integer, BigInteger> myMap = new HashMap<>();

    static {
        myMap.put(0, BigInteger.ZERO); //fibonacci(0)
        myMap.put(1, BigInteger.ONE); //fibonacci(1)
    }

    public static BigInteger fibonacci(int x)
    {
//        System.out.println("x = [" + x + "]");
        return myMap.computeIfAbsent(x, n -> fibonacci(n - 2).add(fibonacci(n - 1)));
    }

    public static void main(String[] args)
    {

        System.out.println("l = " + fibonacci(25));
        System.out.println("myMap = " + myMap);
        System.out.println("myMap = " + myMap.keySet().size());

    }

}

控制台输出:

l = 75025

myMap = {0=0, 1=1, 2=1, 3=2, 4=3, 5=5, 6=8, 7=13, 8=21, 9=34, 10=55, 11=89, 12=144, 13=233, 14=377, 15=610, 16=987, 17=1597, 18=2584, 19=4181, 20=6765, 21=10946, 22=17711, 23=28657, 24=46368}

myMap = 31

memo 只有 25 个元素,但 size 返回 31。如何?这是哈希映射实现中的错误吗?

我将 hashmap 更改为 ConcurrentHashMap,如果我要求第 9 个或更多斐波那契数,它就会挂起。

但是即使是 1000 也可以正确返回 fibanocci 数!

【问题讨论】:

  • 我在运行此代码时收到java.util.ConcurrentModificationException。你在哪个 JDK 版本上运行?
  • 我也尝试了ConcurrentHashMap,它抛出了一个特定的错误(java.lang.IllegalStateException: Recursive update),这表明你真的不应该这样做。
  • HashMap#computeIfAbsent 的 javadoc 对此有一个特殊警告:映射函数不应在计算期间修改此映射。
  • @Aomine 您可以通过循环轻松完成。甚至不需要递归。
  • @Aomine OP is 使用递归方法(方法fibonacci 调用自身两次),但尝试添加memoization 以提高性能。

标签: java hashmap fibonacci


【解决方案1】:

是的,HashMap.computeIfAbsent(K, Function) Javadoc 指出您不应在计算期间修改映射。如果修改方法先检查map是否包含x作为key,然后返回like

public static BigInteger fibonacci(int x) {
    if (!myMap.containsKey(x)) {
        myMap.put(x, fibonacci(x - 2).add(fibonacci(x - 1)));
    }
    return myMap.get(x);
}

然后你会看到(正如我想你所期望的那样)

l = 75025
myMap = {0=0, 1=1, 2=1, 3=2, 4=3, 5=5, 6=8, 7=13, 8=21, 9=34, 10=55, 11=89, 12=144, 13=233, 14=377, 15=610, 16=987, 17=1597, 18=2584, 19=4181, 20=6765, 21=10946, 22=17711, 23=28657, 24=46368, 25=75025}
myMap = 26

【讨论】:

    猜你喜欢
    • 2016-08-26
    • 1970-01-01
    • 2013-03-31
    • 1970-01-01
    • 1970-01-01
    • 2020-01-18
    • 2016-08-04
    • 2018-06-15
    • 2017-12-14
    相关资源
    最近更新 更多