java - 如何维护多个集合,其中一个对象只能存在于一个集合中?

标签 java data-structures

我有一个类和一个枚举,看起来像这样

class Container{
    static int next_id = 0; 
    final int id = next_id++;
    State state = State.one;
}

enum State{
    one, two, three, four, five;
}

我想维护 Container 的多个集合,但维护 Container 的任何实例,它只存在于一个集合中。集合需要线程安全,我不能将容器直接存储在基于散列的集合中,因为它的散列会根据其当前状态发生变化。

--编辑--

为了进一步阐明,这样做的目标是能够检索处于给定状态的所有容器,而不必检查每个容器的状态,因为有数千个容器。

最佳答案

如果不自己编写一些代码,您将无法确保这一点,因为要保持一致性,即容器根据其状态恰好属于一个集合,不仅需要集合的支持,还需要成员的支持。

不管目标语言是java,我可能会建议链表,像这样:

class Container{
    static int next_id = 0; 
    final int id = next_id++;
    final Node<Container> node;
    State state;

    public Container() {
        node = new Node<>(this);
        setState(State.one);
    }

    public void setState(State state) {
        if(this.state != null) node.unlink();
        this.state = state;
        if(this.state != null) this.state.containers.add(node);
    }
}

enum State{
    one, two, three, four, five;
    final List<Container> containers = ...;
}

此代码之所以有效,是因为知道节点后,可以在 O(1) 中取消元素与链表的链接。 (add 当然也是 O(1))。 Java默认链表不暴露节点,每次访问都需要线性查找,效率低下。

鉴于此,下一个最好的办法是使用基于哈希的方法。一些代码仍然可以保留:

  • 设置状态有点复杂,所以逻辑应该放在setter中,而不是在客户端做container.state = ...
  • 只要容器集合是应用程序范围的(提示:在托管环境中,例如应用程序服务器,它们几乎不是!),它们可以直接由枚举维护。否则,给容器一些 Context持有 EnumMap<State, Map<Integer, Container>>或类似的。

结果:

class Container{
    static int next_id = 0; 
    final int id = next_id++;
    State state;

    public Container() {
        setState(State.one);
    }

    public void setState(State state) {
        if(this.state != null) this.state.containers.remove(id);
        this.state = state;
        if(this.state != null) this.state.containers.put(id, node);
    }
}

enum State{
    one, two, three, four, five;
    final Map<Integer, Container> containers = new HashMap<>();
}

使用id作为key,就不用担心自己的hashCode了和 equals实现。


关于可见性:您真的、真的想至少将这些设为私有(private)或默认(我正在查看 State 中的 map )。

关于线程安全:我不想在这里探出头来(我不是专家),而是使用 ConcurrentHashMap s 可能会做很多你需要的事情。另外,同步 setState .如果不这样做,两个并发更新可能会将容器插入到两个映射中。最后,final int id = next_id++;据我所知不是线程安全的,因为++不是原子的。你可以使用 AtomicInteger在这里。

关于java - 如何维护多个集合,其中一个对象只能存在于一个集合中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23811098/

相关文章:

c++ - 实现弹出最常添加项目的堆栈

swift - 在 Swift 中获取带有前提条件的子序列的有效方法

java - 基于Object.class创建类

java - 隐式 super 构造函数 StudentTest() 未定义。必须显式调用另一个构造函数”

java - 在 JInnerFrame 中使用 AWT 组件(对于 JDesktopPane)

c - 在 BST 中找到给定总和的一对

c - 之字形树打印

java - 使用 htmlunit 访问 html 表

java - 线程获取已被其他线程获取的 ReentrantLock

algorithm - Prolog中信息检索的性能优化