Reputation: 18572
I have used HashMap
for storing Fibonacci values.
Here is output from this code execution:
Enter n: 500000
F(500000) = 2955561408 ... computed in 5,141 ms
Enter n: 500000
F(500000) = 2955561408 ... computed in 0 ms
It caches just fine, and returns result just fine
I want to replace it with much better Guava cache
, I have lost any profit.
Code execution output:
Enter n: 500000
F(500000) = 2955561408 ... computed in 5,184 ms
Enter n: 500000
F(500000) = 2955561408 ... computed in 5,086 ms
Here is program code:
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;
}
}
}
}
As I suppose when you call cachedFibonacci.getUnchecked()
it should return cached value if it is cached, otherwise compute it and cache.
Why does this code calculate it again with Guava cache?
How to solve this issue?
Upvotes: 0
Views: 1201
Reputation: 4532
If you remove line
.weakKeys()
from building cache, than you will see speed up of calculation.
From javaDoc
Warning: when this method is used, the resulting cache will use identity ({@code ==})
- comparison to determine equality of keys.
Upvotes: 5