Eliminate allocs - String Caches now have Prim subtypes (#1892)

By creating versions of the FormattedStringCache that don't require auto boxing, allocations are cut tremendously in this commit.
diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java
index a080de8..efe51d2 100644
--- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java
+++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java
@@ -165,15 +165,15 @@
 
     private class ValueFormatter implements com.github.mikephil.charting.formatter.ValueFormatter {
 
-        private FormattedStringCache<Integer, Float> mFormattedStringCache;
+        private FormattedStringCache.PrimIntFloat mFormattedStringCache;
 
         public ValueFormatter() {
-            mFormattedStringCache = new FormattedStringCache<>(new DecimalFormat("######.0"));
+            mFormattedStringCache = new FormattedStringCache.PrimIntFloat(new DecimalFormat("######.0"));
         }
 
         @Override
         public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) {
-            return mFormattedStringCache.getFormattedString(value, dataSetIndex);
+            return mFormattedStringCache.getFormattedValue(value, dataSetIndex);
         }
     }
 }
diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java
index 3369e00..f55fc81 100644
--- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java
+++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java
@@ -12,7 +12,7 @@
     /**
      * FormattedStringFormat for formatting and caching
      */
-    protected FormattedStringCache<Float, Float> mFormattedStringCache;
+    protected FormattedStringCache.PrimFloat mFormattedStringCache;
 
     /**
      * the number of decimal digits this formatter uses
@@ -35,14 +35,14 @@
             b.append("0");
         }
 
-        mFormattedStringCache = new FormattedStringCache<>(new DecimalFormat("###,###,###,##0" + b.toString()));
+        mFormattedStringCache = new FormattedStringCache.PrimFloat(new DecimalFormat("###,###,###,##0" + b.toString()));
     }
 
     @Override
     public String getFormattedValue(float value, AxisBase axis) {
 
         // TODO: There should be a better way to do this.  Floats are not the best keys...
-        return mFormattedStringCache.getFormattedString(value, value);
+        return mFormattedStringCache.getFormattedValue(value);
 
     }
 
diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/FormattedStringCache.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/FormattedStringCache.java
index 047af77..cb0508b 100644
--- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/FormattedStringCache.java
+++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/FormattedStringCache.java
@@ -1,6 +1,7 @@
 package com.github.mikephil.charting.formatter;
 
 import java.text.Format;
+import java.util.ArrayList;
 import java.util.HashMap;
 
 /**
@@ -17,7 +18,7 @@
  */
 public class FormattedStringCache<K, V> {
 
-    private Format mFormat;
+    protected Format mFormat;
     private HashMap<K, String> mCachedStringsHashMap = new HashMap<>();
     private HashMap<K, V> mCachedValuesHashMap = new HashMap<>();
 
@@ -48,4 +49,81 @@
         return result;
     }
 
+    public static class PrimIntFloat extends FormattedStringCache{
+
+        public PrimIntFloat(Format format){
+            super(format);
+        }
+
+        private ArrayList<Float> cachedValues = new ArrayList<>();
+        private ArrayList<String> cachedStrings = new ArrayList<>();
+
+        public String getFormattedValue(float value, int key) {
+
+            boolean hasValueAtdataSetIndex = true;
+            if(cachedValues.size() <= key){
+                int p = key;
+                while(p >= 0){
+                    if(p == 0){
+                        cachedValues.add(value);
+                        cachedStrings.add("");
+                    }else{
+                        cachedValues.add(Float.NaN);
+                        cachedStrings.add("");
+                    }
+                    p--;
+                }
+                hasValueAtdataSetIndex = false;
+            }
+
+            if(hasValueAtdataSetIndex) {
+                Float cachedValue = cachedValues.get(key);
+                hasValueAtdataSetIndex = !(cachedValue == null || cachedValue != value);
+            }
+
+            if(!hasValueAtdataSetIndex){
+                cachedValues.set(key, value);
+                cachedStrings.set(key, mFormat.format(value));
+            }
+
+            return cachedStrings.get(key);
+        }
+
+    }
+
+    public static class PrimFloat extends FormattedStringCache{
+
+        public PrimFloat(Format format){
+            super(format);
+        }
+
+
+        private ArrayList<Float> cachedValues = new ArrayList<>();
+        private ArrayList<String> cachedStrings = new ArrayList<>();
+
+        public String getFormattedValue(float value) {
+
+            boolean alreadyHasValue = false;
+            int vCount =  cachedValues.size();
+            int sIndex = -1;
+            for(int i = 0 ; i < vCount ; i++){
+                if(cachedValues.get(i) == value){
+                    sIndex = i;
+                    alreadyHasValue = true;
+                    break;
+                }
+            }
+             if(!alreadyHasValue) {
+                 cachedValues.add(value);
+                 cachedStrings.add(mFormat.format(value));
+                 sIndex = cachedValues.size() - 1;
+             }
+
+            return cachedStrings.get(sIndex);
+        }
+
+    }
+
+
+
 }