Java时间稀疏的1D数组(双)

时间:2009-12-10 12:54:29

标签: java time sparse-array

我需要一个高效的Java结构来操作非常稀疏的双精度向量:基本的读/写操作。我在HashMap中实现它但访问速度太慢。我应该使用其他数据结构吗?你推荐任何免费图书馆吗?

寻求一些和平的建议:)

非常感谢,

玛丽

4 个答案:

答案 0 :(得分:3)

HashMap是要走的路。它应该不慢。通过分析器运行代码以查看所有时间的位置,然后进行相应的优化。如果您需要有关优化代码的提示,请在此处发布示例,以便我们为特定问题提供帮助。

[编辑]根据索引的大小,您可以使用Integer.valueOf(int)中的技术来缓存装箱对象。但这只适用于创建大量地图且索引范围有限的情况。

或者您可以从commons-lang尝试IntHashMap。它有点难以使用(它的包是私有的)但你可以复制代码。

最后,您可以使用自己的基于int的HashMap实现,并为您的案例优化值查找。

答案 1 :(得分:1)

您的数据集有多大?远大于Integer.MAX_VALUE?问题是HashSet由数组支持。碰撞会降低性能。也许这不是hashmap的机制太慢,而是你有多次碰撞的事实。也许如果您首先使用另一个哈希函数对数据进行分区(例如),那么将每个数据分区存储在自己的哈希映射中,您就会有更多的运气。

答案 2 :(得分:0)

您可以复制粘贴我的Hapax项目中的稀疏矢量:ch.akuhn.matrix.SparseVector

PS:对所有其他答案和评论不要理解为什么使用地图太慢了。它很慢,因为地图将所有索引都装入Integer对象!

此处提供的稀疏向量对于读取访问和附加值来说是快速的,但不适用于随机索引。它适用于首先创建sprase向量但按增加索引的顺序放置值的场景,以及稍后使用map进行读取的场景。

稀疏矢量类中的重要方法是

// ...

public class SparseVector {

    /*default*/ int[] keys;
    /*default*/ int size, used;
    /*default*/ double[] values;

    public SparseVector(int size, int capacity) {
        assert size >= 0;
        assert capacity >= 0;
        this.size = size;
        this.keys = new int[capacity];
        this.values = new double[capacity];
    }

    public double get(int key) {
        if (key < 0 || key >= size) throw new IndexOutOfBoundsException(Integer.toString(key));
        int spot = Arrays.binarySearch(keys, 0, used, key);
        return spot < 0 ? 0 : values[spot];
    }

    public boolean isUsed(int key) {
        return 0 <= Arrays.binarySearch(keys, 0, used, key);
    }

    public double put(int key, double value) {
        if (key < 0 || key >= size) throw new IndexOutOfBoundsException(Integer.toString(key));
        int spot = Arrays.binarySearch(keys, 0, used, key);
        if (spot >= 0) return values[spot] = (float) value;
        else return update(-1 - spot, key, value);
    }

    public void resizeTo(int newSize) {
        if (newSize < this.size) throw new UnsupportedOperationException();
        this.size = newSize;
    }

    public int size() {
        return size;
    }

    private double update(int spot, int key, double value) {
        // grow if reaching end of capacity
        if (used == keys.length) {
            int capacity = (keys.length * 3) / 2 + 1;
            keys = Arrays.copyOf(keys, capacity);
            values = Arrays.copyOf(values, capacity);
        }
        // shift values if not appending
        if (spot < used) {
            System.arraycopy(keys, spot, keys, spot + 1, used - spot);
            System.arraycopy(values, spot, values, spot + 1, used - spot);
        }
        used++;
        keys[spot] = key;
        return values[spot] = (float) value;
    }

    public int used() {
        return used;
    }

    public void trim() {
        keys = Arrays.copyOf(keys, used);
        values = Arrays.copyOf(values, used);
    }

}

答案 3 :(得分:0)

对于1D稀疏数组,map通常是要走的路。如果库是多维的,您只需要使用它。

如果比较地图和数组之间的访问时间,

   map.get(99);
   array[99];

地图会慢得多。任何图书馆都会遇到同样的问题。

稀疏阵列是什么?你换时间换空间。