【问题标题】:How to use Guava cache instead of HashMap?如何使用 Guava 缓存而不是 HashMap?
【发布时间】:2015-10-09 15:41:02
【问题描述】:

我使用HashMap 来存储斐波那契值。

这是这段代码执行的输出:

Enter n: 500000
F(500000) = 2955561408 ... computed in 5,141 ms
Enter n: 500000
F(500000) = 2955561408 ... computed in 0 ms

缓存很好,返回结果也很好

我想用更好的Guava cache 替换它,我已经失去了任何利润。 代码执行输出:

Enter n: 500000
F(500000) = 2955561408 ... computed in 5,184 ms
Enter n: 500000
F(500000) = 2955561408 ... computed in 5,086 ms

这是程序代码:

public class CachedFibonacci {
    private static Map<BigDecimal, BigDecimal> previousValuesHolder;
    static {
        previousValuesHolder = new HashMap<>();
        previousValuesHolder.put(BigDecimal.ZERO, BigDecimal.ZERO);
        previousValuesHolder.put(BigDecimal.ONE, BigDecimal.ONE);
    }

    private static LoadingCache<BigDecimal, BigDecimal> cachedFibonacci = CacheBuilder.newBuilder()
            .expireAfterWrite(3, TimeUnit.MINUTES)
            .maximumSize(500000)
            .concurrencyLevel(5)
            .weakKeys()
            .build(new CacheLoader<BigDecimal, BigDecimal>() {
                @Override
                public BigDecimal load(BigDecimal key) throws Exception {
                    return getFibonacciByKey(key);
                }
            });

    private static BigDecimal getFibonacciByKey(BigDecimal key) {
        long number = key.longValue();

        BigDecimal olderValue = BigDecimal.ONE,
                oldValue = BigDecimal.ONE,
                newValue = BigDecimal.ONE;

        for (int i = 3; i <= number; i++) {
            newValue = oldValue.add(olderValue);
            olderValue = oldValue;
            oldValue = newValue;
        }
        return newValue;
    }

    public static BigDecimal getGuavaCache(long number) {
        if (0 == number) {
            return BigDecimal.ZERO;
        } else if (1 == number) {
            return BigDecimal.ONE;
        } else {
            return cachedFibonacci.getUnchecked(BigDecimal.valueOf(number));
        }
    }

    public static BigDecimal getCachedFibonacciOf(long number) {
        if (0 == number) {
            return BigDecimal.ZERO;
        } else if (1 == number) {
            return BigDecimal.ONE;
        } else {
            if (previousValuesHolder.containsKey(BigDecimal.valueOf(number))) {
                return previousValuesHolder.get(BigDecimal.valueOf(number));
            } else {
                BigDecimal olderValue = BigDecimal.ONE,
                        oldValue = BigDecimal.ONE,
                        newValue = BigDecimal.ONE;

                for (int i = 3; i <= number; i++) {
                    newValue = oldValue.add(olderValue);
                    olderValue = oldValue;
                    oldValue = newValue;
                }
                previousValuesHolder.put(BigDecimal.valueOf(number), newValue);
                return newValue;
            }
        }
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        while (true) {
            System.out.print("Enter n: ");
            long inputNumber = scanner.nextLong();
            if (inputNumber >= 0) {
                long beginTime = System.nanoTime();
//                BigDecimal fibo = getCachedFibonacciOf(inputNumber);
                BigDecimal fibo = getGuavaCache(inputNumber);

                long endTime = System.nanoTime();
                long delta = endTime - beginTime;

                System.out.printf("F(%d) = %.10s ... computed in %,d ms\n", inputNumber, fibo, delta / 1_000_000);
            } else {
                System.err.println("You must enter number > 0");
                System.out.println("try, enter number again, please:");
                break;
            }
        }
    }
}

我想当你调用 cachedFibonacci.getUnchecked() 时,如果它被缓存,它应该返回缓存值,否则计算它并缓存。

为什么这段代码要用 Guava 缓存再次计算?
如何解决这个问题?

【问题讨论】:

  • “F(500000)”是指斐波那契数列中的第 500,000 个数字吗?那么答案肯定是不正确的,因为这个数字比 2955561408 大很多。即使是 F(48) 也已经是一个更大的数字了。
  • @Jesper 我相信“...”作者的意思是其余的数字。
  • @Jesper 是的,完全正确。为了方便起见,我截断了输出。我只打印了 fibo 值的前 10 个数字。
  • @bezmax 正是这个。否则结果会太冗长。谢谢。
  • @nazar_art 我想知道你为什么使用弱键。我建议删除该设置并检查没有它的缓存如何执行。

标签: java caching guava


【解决方案1】:

如果你删除线

.weakKeys()

从建立缓存,你会看到计算速度。

来自 javaDoc

  • 警告:使用此方法时,生成的缓存将使用标识 ({@code ==})

  • 比较以确定键的相等性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-02-20
    • 2015-04-02
    • 1970-01-01
    • 2023-03-20
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多