// %1030546705355:de.spieleck.util%
package de.spieleck.util;


/**
 * This subclass of {@link de.spieleck.util.SpeedHashtable} is specially
 * taylored for the keys of Strings as keys in a Hashtable. The point
 * is to avoid the O(stringlen) calculation of the hashCode of
 * a String.
 *
 * @author fsn
 * @version 1
 */
public class StringKeyHashtable
 extends SpeedHashtable
{
    public final static int EXP = 19;

    public StringKeyHashtable(int n)
    {
        super(n);
    }

    public StringKeyHashtable()
    {
        super();
    }

    /**
     * Replace the usual java hashCode for Strings by something
     * faster. Note it is fairly easy to construct a sequence of
     * Strings which actually spoil this optimization by all having
     * the same hash. This is considered unlikely in real world
     * applications.
     */
    protected int hashCode(Object o)
    {
        if (!(o instanceof java.lang.String))
            return o.hashCode();
        else
            return stringHashCode((String)o);
    }

    public static int stringHashCode(String s)
    {
        int len = s.length();
        if (len < 15)
            return s.hashCode();

        return (((((((s.charAt(1) * EXP - s.charAt(len - 1)) * EXP
                                   + s.charAt(3)) * EXP
                               - s.charAt(len - 3)) * EXP + s.charAt(6)) * EXP
                       - s.charAt(len - 6)) * EXP + s.charAt(len / 2)) * EXP)
               ^ len;
    }

    protected final static int LENGTH = 100000;

    public static void main(String[] args)
    {
        int i;
        int dummy;
        StringKeyHashtable st = new StringKeyHashtable();
        String[] test         = new String[LENGTH];
        for (i = 0; i < LENGTH; i++)
            test[i] = "" + i;
        for (int j = 0; j < 10; j++)
        {
            long t1 = System.currentTimeMillis();
            dummy = 0;
            for (i = 0; i < LENGTH; i++)
                dummy ^= test[i].hashCode();
            long t2 = System.currentTimeMillis();
            for (i = 0; i < LENGTH; i++)
                dummy ^= st.hashCode(test[i]);
            long t3 = System.currentTimeMillis();
            System.out.println(
                    "*** j=" + j + ", old="+(t2-t1)+", new="+(t3-t2));
            for (i = 0; i < LENGTH; i++)
                test[i] = "e" + test[i] + test[i];
        }
    }
}