I used ehcache with ehcache-spring-annotations. The first time, we choose HashCodeCacheKeyGenerator. It was pretty good. but 1 month ago we found "key duplication". So we replaced HashCodeCacheKeyGenerator with StringCacheKeyGenerator. "key duplication" issue gone, but huge toString(using apache ToStringBuilder) key allocated heap memory(about 200M) Because parameter object(value object) have huge field.
I made very very simple tostring like below
VerySimpleToStringStyle$Ta,,,,,1|2|3,1|2|3,a|b|c,true|false,64|65|66,1.0|2.0|3.0,1.0|2.0|3.0,,,,,,,1|2|3,[a, b, c],{b=2, c=3, a=1},a|1|false|{b=2, c=3, a=1}|[a, b, c],A,[b, c, a],,,
As you can see, no field name and no value if the value is null. I hope to use SHA256, MD5 hashing about the original toString, but coworker and i worry about "key duplicated".
Any idea shortest toString method of huge value object as ehcache key?
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
public class VerySimpleToStringStyle extends ToStringStyle {
private static final long serialVersionUID = -8388711512639784062L;
public VerySimpleToStringStyle() {
super();
this.setUseClassName(true);
this.setUseIdentityHashCode(false);
this.setUseFieldNames(false);
this.setContentStart("");
this.setContentEnd("");
this.setNullText("");
this.setFieldSeparatorAtStart(false);
this.setFieldSeparator(",");
this.setFieldSeparatorAtEnd(false);
this.setArrayStart("");
this.setArraySeparator("|");
this.setArrayEnd("");
}
private static class T {
private String a = "a";
private String a1 = null;
private String cc1;
private String cc2;
private String cc3;
private int[] i = new int[] {1, 2, 3};
private long[] l = new long[] {1, 2, 3};
private char[] c = new char[] {'a', 'b', 'c'};
private boolean[] bl = new boolean[] {true, false};
private byte[] b = new byte[] {64, 65, 66};
private float[] f = new float[] {1, 2, 3};
private double[] d = new double[] {1, 2, 3};
private String bb1;
private String bb2;
private String bb3;
private String bb4;
private String bb5;
private String bb6;
private short[] s = new short[] {1, 2, 3};
private List<String> list = new ArrayList<String>();
private Map<String, String> m = new HashMap<String, String>();
private Object[] o = new Object[] {"a", 1, false, m, list};
private enum E {A, B, C};
private E e = E.A;
private static String x = "x";
private transient String y = "y";
private Set<String> set = new HashSet<String>();
private String aa1;
private String aa2;
private String aa3;
public T() {
this.list.add("a");
this.list.add("b");
开发者_如何学C this.list.add("c");
this.m.put("a", "1");
this.m.put("b", "2");
this.m.put("c", "3");
this.set.add("a");
this.set.add("b");
this.set.add("c");
}
}
public static void main(String[] args) {
System.out.println(ToStringBuilder.reflectionToString(new T(), new VerySimpleToStringStyle()));
}
}
Hash functions like sha256 and MD5 would mostly be fine. The Duplicated key problem is normally referred as key collision. There is ABSOLUTELY no way to make sure collision will not happen because, there are finite possibilities as hash function would generate. The quality of the hash function would make collision less likely but not impossible.
To make sure collision never happen yet reduce the size of the generated key, what you can do is to maximize the entropy in the key generated using the values. In simpler words, use a compression function to be the key. However, in your case, the toString builder seems have taken all info about the object to build the key, that defeats the purpose of having a cache as the key already holding all the information you need. Instead, the key should be some kind of unique identifier of the object you are trying to cache.
So firstly, identify what can be used as the unique identifier as the key is more important than how to generate one.
And figure out a way to handle collision.
Just as the first answer said the answer is to use a real hashing function. The default key generator just uses the Java hashCode method.
Try MessageDigestCacheKeyGenerator: the http://code.google.com/p/ehcache-spring-annotations/wiki/MessageDigestCacheKeyGenerator
It can use any hashing algorithm supported by the Java MessageDigest API, the default configuration generates a SHA-1 hash of the key data.
精彩评论