F(n) = F(n-1) + F(n-2) F(0) = 0 F(1) = 1
0,1,1,2,3,5,8,13,21,34,55,89,...
package com.snail.exam.aj.fibonacci;
public class Fibonacci {
  public static void main(String[] args){
    for( int n = 0 ;  n < 50 ; n++ ){
      
      double now = System.currentTimeMillis() * 1000000.0 + System.nanoTime();
      
      long fn = fibonacci(n);
            
      double end = System.currentTimeMillis() * 1000000.0 + System.nanoTime();
      
      System.out.println( n + ",F(" + n + ")=" + fn + "," + (end - now)/1000000000.0);
    }
  }
  
  public static long fibonacci(int n){
    if( n == 0 ){
      return 0;
    }
    if( n == 1 ){
      return 1;
    }
    return fibonacci(n-2) + fibonacci(n-1);
  }
}
あんまり遅いので、Fibonacci#fibonacci(n) の結果をキャッシングする Aspect を適用する。
package com.snail.exam.aj.fibonacci;
import java.util.LinkedHashMap;
import java.util.Map;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class FibonacciCache {
  
  private static final int MAX_ENTRIES = 2;
  private static Map<Integer,Long> cache = new LinkedHashMap<Integer,Long>(){
    @Override
    protected boolean removeEldestEntry(Map.Entry<Integer,Long> eldest) {
      return size() > MAX_ENTRIES;
           }
  };
  
  public static int getCacheSize(){
    return cache.size();
  }
  
  @Around("call(long com.snail.exam.aj.fibonacci.Fibonacci.fibonacci(int))")
  public long cacheFibonacci(ProceedingJoinPoint thisJoinPoint) throws Throwable{
    
    Object[] args = thisJoinPoint.getArgs();
    Integer arg = (Integer)args[0];
    
    if(!cache.containsKey(arg)){
      cache.put(arg, (Long)thisJoinPoint.proceed(thisJoinPoint.getArgs()));
    }
    
    return cache.get(arg);
  }
}