RATIS-2099. Cache TermIndexImpl instead of using anonymous class (#1100)

diff --git a/ratis-server-api/src/main/java/org/apache/ratis/server/protocol/TermIndex.java b/ratis-server-api/src/main/java/org/apache/ratis/server/protocol/TermIndex.java
index 7def686..6a9bd1c 100644
--- a/ratis-server-api/src/main/java/org/apache/ratis/server/protocol/TermIndex.java
+++ b/ratis-server-api/src/main/java/org/apache/ratis/server/protocol/TermIndex.java
@@ -19,13 +19,21 @@
 
 import org.apache.ratis.proto.RaftProtos.LogEntryProto;
 import org.apache.ratis.proto.RaftProtos.TermIndexProto;
+import org.apache.ratis.thirdparty.com.google.common.cache.Cache;
+import org.apache.ratis.thirdparty.com.google.common.cache.CacheBuilder;
 
 import java.util.Comparator;
 import java.util.Optional;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
 
 /** The term and the log index defined in the Raft consensus algorithm. */
 public interface TermIndex extends Comparable<TermIndex> {
-  TermIndex[] EMPTY_ARRAY = {};
+  /** An LRU Cache for {@link TermIndex} instances */
+  Cache<TermIndex, TermIndex> PRIVATE_CACHE = CacheBuilder.newBuilder()
+      .maximumSize(1 << 16)
+      .expireAfterAccess(1, TimeUnit.MINUTES)
+      .build();
 
   /** @return the term. */
   long getTerm();
@@ -60,7 +68,7 @@
 
   /** @return a {@link TermIndex} object. */
   static TermIndex valueOf(long term, long index) {
-    return new TermIndex() {
+    final TermIndex key = new TermIndex() {
       @Override
       public long getTerm() {
         return term;
@@ -98,5 +106,10 @@
         return String.format("(t:%s, i:%s)", longToString(term), longToString(index));
       }
     };
+    try {
+      return PRIVATE_CACHE.get(key, () -> key);
+    } catch (ExecutionException e) {
+      throw new IllegalStateException("Failed to valueOf(" + term + ", " + index + "), key=" + key, e);
+    }
   }
 }
\ No newline at end of file