Java 作为ehcache密钥的最短toString

Java 作为ehcache密钥的最短toString,java,ehcache,Java,Ehcache,我将ehcache与ehcache-spring注释一起使用。 第一次,我们选择HashCodeCacheKeyGenerator。非常好。 但一个月前我们发现了关键的重复。 因此,我们将HashCodeCacheKeyGenerator替换为StringCacheKeyGenerator。 密钥复制问题消失了,但巨大的ToString使用apache ToString Builder密钥分配了大约2亿个堆内存 因为参数objectvalue对象有巨大的字段 我做了一个非常非常简单的字符串,如下

我将ehcache与ehcache-spring注释一起使用。 第一次,我们选择HashCodeCacheKeyGenerator。非常好。 但一个月前我们发现了关键的重复。 因此,我们将HashCodeCacheKeyGenerator替换为StringCacheKeyGenerator。 密钥复制问题消失了,但巨大的ToString使用apache ToString Builder密钥分配了大约2亿个堆内存 因为参数objectvalue对象有巨大的字段

我做了一个非常非常简单的字符串,如下所示

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],,,
如您所见,如果值为null,则没有字段名和值。 我希望对原始toString使用SHA256、MD5哈希,但我和同事担心密钥重复

有没有想过将大值对象作为ehcache密钥的最短串方法

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");
        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()));
}
}

像sha256和MD5这样的散列函数基本上可以。复制密钥问题通常称为密钥冲突。绝对无法确保冲突不会发生,因为哈希函数会生成有限的可能性。哈希函数的质量会降低冲突的可能性,但并非不可能

为了确保不会发生冲突,同时减小生成的键的大小,您可以做的是最大化使用这些值生成的键中的值。简单地说,使用压缩函数作为键。但是,在您的例子中,toString生成器似乎已经获取了有关对象的所有信息来构建密钥,这与将缓存作为密钥来保存您所需的所有信息的目的背道而驰。相反,密钥应该是您试图缓存的对象的某种唯一标识符

因此,首先,确定什么可以用作唯一标识符,因为密钥比如何生成密钥更重要


然后找出处理冲突的方法。

正如第一个答案所说,答案是使用真正的哈希函数。默认密钥生成器仅使用Java hashCode方法

尝试MessageDigestCacheKeyGenerator:

它可以使用Java MessageDigest API支持的任何哈希算法,默认配置生成密钥数据的SHA-1哈希