Java 堆栈和散列联合

Java 堆栈和散列联合,java,algorithm,hash,stack,Java,Algorithm,Hash,Stack,我正在尝试编写一个数据结构,它是堆栈和HashSet的组合,具有快速push/pop/membership(我正在寻找常量时间操作)。想想Python的OrderedDict 我尝试了一些方法,得到了以下代码:和。我需要向源代码中添加一些文档,但基本上我使用带有线性探测的哈希来将索引存储在键向量中。由于线性探测总是将最后一个元素放在已填充单元格的连续范围的末尾,因此pop()可以非常容易地实现,而无需复杂的删除操作 我有以下问题: 数据结构消耗大量内存(一些改进是显而易见的:stackKeys

我正在尝试编写一个数据结构,它是堆栈和HashSet的组合,具有快速push/pop/membership(我正在寻找常量时间操作)。想想Python的OrderedDict

我尝试了一些方法,得到了以下代码:和。我需要向源代码中添加一些文档,但基本上我使用带有线性探测的哈希来将索引存储在键向量中。由于线性探测总是将最后一个元素放在已填充单元格的连续范围的末尾,因此pop()可以非常容易地实现,而无需复杂的删除操作

我有以下问题:

  • 数据结构消耗大量内存(一些改进是显而易见的:
    stackKeys
    比需要的大)
  • 有些操作比使用fastutil慢(例如:pop(),在某些情况下甚至是push())。我尝试使用fastutil和trove4j重写这些类,但我的应用程序的总体速度降低了一半
您对我的代码有什么性能改进建议?
你知道我可以尝试什么开源库/代码吗?

我认为你想要的(几乎)已经在库中可用了:LinkedHashSet是一个具有基础双链接列表的散列集(这使它更容易使用)。LinkedHashMap甚至有一个RemoveDestrentry,听起来很像pop方法

简单解决方案的性能如何,如:

类HashStack{

private HashMap counts=new HashMap();
私有堆栈=新堆栈();
公共无效推送(T){
叠加推力(t);
counts.put(t,1+getCount(t));
}
公共广播电台{
T=stack.pop();
counts.put(t,counts.get(t)-1);
返回t;
}
私有整数getCount(T){
返回计数.containsKey(t)?计数.get(t):0;
}
公共布尔包含(T){
返回getCount(t)>0;
}
公共字符串toString(){
返回stack.toString();
}
}

我建议使用,因为它为添加、删除和包含提供了保证的O(logn)成本。

您已经有了一个非常好的实现。对我来说唯一明显的改进是,当弹出窗口时,通过搜索,你做了比你需要做的更多的工作。您不应该在堆栈中存储键本身,而应该将索引存储到键数组中。当你想偷看最后一个项目时,这会让你以一个指针间接指向为代价快速弹出窗口


除此之外,只需调整堆栈的大小以加载_FACTOR*(heap array size),您就可以在满足速度要求的情况下,以尽可能少的内存实现最快的速度。

承认这一点,您只需要在同一句话中使用hash和joint;-)标准API中是否有一个类可以满足您的需求?可能是
java.util.concurrent.ConcurrentSkipListMap
?“其键的自然排序”<代码>ConcurrentSkipListMap不保留插入顺序。但是我正在研究
LinkedHashMap
。Alexandru您是想用fast contains()和university实现堆栈,还是仅仅用fast contains()实现堆栈?两者都是:fast university和fast contains。您的解决方案很好,但我已经用fastutil实现了一个类似的解决方案,它可能更快,因为fastutil使用原语。我正在寻找哈希表和堆栈的组合,如果可能的话,它使用单个表。现在我的内存需求大约是插入的密钥大小的3倍,而且我没有缓存感知,因为我总是在两个表中查找。但这应该是可以用固定时间进行摊销的,不是吗?这是我所希望的技巧。我认为将索引存储在
stackKey
数组中会大大加快pop()函数的速度。我明天会测试它。它工作得很好:从最初的测试来看,它()提高了2倍,pop()提高了4倍,push()只稍微提高了一点。最大的收益来自搜索()中删除的重定向。
    private HashMap<T, Integer> counts = new HashMap<T, Integer>();
    private Stack<T> stack = new Stack<T>();

    public void push(T t) {
        stack.push(t);
        counts.put(t, 1 + getCount(t));
    }

    public T pop() {
        T t = stack.pop();
        counts.put(t, counts.get(t) - 1);
        return t;
    }

    private int getCount(T t) {
        return counts.containsKey(t) ? counts.get(t) : 0;
    }

    public boolean contains(T t) {
        return getCount(t) > 0;
    }

    public String toString() {
        return stack.toString();
    }
}