用Java替换大数组?

时间:2016-12-26 00:17:40

标签: java arrays performance data-structures

我有一个长度为614 125的对象数组。 重点是通过获取每个字节值的模数85来从3个字节的数字中获取索引。

它是一个很大的阵列,但FAR低于允许的极限,但它速度极慢,尽管有直接索引访问(我实际上从不迭代数组)。

问题在于我使用的是散乱值(3个字节),这是我事先无法知道的,因此我无法预测该值,也不能将其缩小。我的想法似乎很聪明,但阵列太大了,这让我的游戏慢了两倍。

这种情况有替代方案吗?请注意,我已经尝试过HashMap,但它更慢,因为我的哈希值太远了。

我试图找到一种不从一开始就分配大型数组的方法,而是动态添加新对象。使用我的Node对象" next"和"之前"会解决问题并且会很快排序,但是我无法找到一种方法来找到没有O(N / 2)顺序的散列,这太长了(我想要O(1))。

以下是代码,如果有任何用处:

HashMap中

public class HashMap {
    public static final int ARRAY_SIZE = 614125;
    // This value represents 255/3 (max byte value)=> hash is 3 bytes long:
    // First byte%85 gives us the first index, same for second and third.
    private static final int MODULO = 85;
    private static final int FIRST_MULTIPLIER = 7225;
    private static final int SECOND_MULTIPLIER = 85;

    private Node[] mHashMap;
    private int index1, index2, index3;

    public HashMap() {
        mHashMap = new Node[ARRAY_SIZE];
    }

    public void put(int hash, int value) {
        index1 = (hash & 0xFF) % MODULO;
        index2 = ((hash >> 8) & 0xFF) % MODULO;
        index3 = ((hash >> 16) & 0xFF) % MODULO;
        int index = index1 * FIRST_MULTIPLIER + index2 * SECOND_MULTIPLIER + index3;
        Node node = mHashMap[index];
        if (node == null) {
            mHashMap[index] = new Node(value);
        } else {
            node.addValue(value);
        }
    }

    public Node get(int hash) {
        index1 = (hash & 0xFF) % MODULO;
        index2 = ((hash >> 8) & 0xFF) % MODULO;
        index3 = ((hash >> 16) & 0xFF) % MODULO;
        int index = index1 * FIRST_MULTIPLIER + index2 * SECOND_MULTIPLIER + index3;
        return mHashMap[index];
    }
}

节点

public class Node {
    private Node mNext;
    private int mValue;

    public Node(int value) {
        mValue = value;
        mNext = null;
    }

    public void setNext(Node next) {
        mNext = next;
    }

    public boolean hasNext() {
        return mNext != null;
    }

    public Node next() {
        return mNext;
    }

    public int getValue() {
        return mValue;
    }

    public void addValue(int value) {
        mValue += value;
    }
}

1 个答案:

答案 0 :(得分:0)

  

我试图找到一种不从一开始就分配大型数组的方法,而是动态添加新对象。

为什么呢? IIUYC您不需要最小化内存消耗。使用较少的内存可能会导致速度增加,但我认为它不适用于此。

罪魁祸首很可能是你的哈希计算速度很慢。多次执行%非常昂贵,此处不需要。如果要将int映射到数组索引,可以使用单个模数(当数组大小为素数时很好)或根本没有慢速操作(当数组大小是2的幂。)

我建议像

这样的东西
private static final int LOG_ARRAY_SIZE = 19;
private static final int ARRAY_SIZE = 1 << LOG_ARRAY_SIZE;

private int toIndex(int x) {
    return (x * 0xcc9e2d51) >>> (32-LOG_ARRAY_SIZE);
}

public void put(int hash, int value) {
    index = toIndex(hash);
    Node node = mHashMap[index];
    if (node == null) {
        mHashMap[index] = new Node(value);
    } else {
        node.addValue(value);
    }
}

public Node get(int hash) {
    index = toIndex(hash);
    return mHashMap[index];
}