2

我想在java中实现一个不透明的句柄。

即,当用户在我的工厂类类上调用 Create 时,我创建了该类的一个对象,但不返回对象本身,而是返回一个表示类实例的 int。我将有一个HashMap将 int 存储为键和对象作为值的存储。该类的每个其他方法都将一个 int 作为一个参数,它将从中检索对象HashMap并对相应的对象执行所需的操作。将有一个 remove 方法将其从 中删除HashMap并允许它被垃圾收集。

我想知道是否有任何现有的类/数据结构可以避免我必须实现代码的句柄部分?

我认为我不能使用hashCodeoridentityHashCode作为唯一标识符,因为不能保证它们是唯一的。

如果我自己实现一个运行计数器,我将不得不在创建唯一 ID 时处理线程安全等问题,当我从hashMap等中删除对象时重用 id。所以我想知道是否有任何现有的类可以帮助解决这个问题.

4

4 回答 4

1

我会保留自己的柜台。如果您担心线程安全,请使用AtomicInteger 。

而且我不会尝试重复使用 id:这将使调试和日志记录变得非常困难。您不太可能用完整数。

于 2013-02-15T10:45:53.123 回答
1

取长值作为 id。你永远不会耗尽多头。重新使用 int 会带来更高的复杂性和速度变慢。
使用同步(或私有锁对象)编写 get() set() 和 increment() 很简单。否则AtomicLongincrementAndGet()

于 2013-02-17T12:20:24.500 回答
1

让我们做简单的计算。您说您将拥有最多 10000 个对象,最多 1 小时的存活时间。让我们假设更苛刻的条件 - 每 1 分钟 10000 个对象。32 位整数足以使用大约 1 年。此外,即使整数溢出,它也会再次从零开始,重用一年前使用的整数。如我所见,这绰绰有余。因此,只需使用 AtomicInteger 即可,它的运行速度非常快,足以满足您的要求。

如果你仍然有疑问,你可以有一个更有弹性的解决方案——当一个新的句柄生成时,首先检查 HashMap 是否已经有这个键(这是非常快的操作),如果有,只需选择下一个整数。它类似于操作系统中的https://superuser.com/questions/135007/how-are-pids-generated 。

于 2013-02-22T11:47:11.397 回答
0

我建议您使用返回封装对象的基本 OO 设计 - 它简单、强大且众所周知。

不要从工厂返回 int 并将其传递给工厂方法。相反,为新创建的对象(抽象数据类型)声明一个特定类并返回此 ADT 类的实例。将操作对象的方法从工厂移动到 ADT 类。

例如

// file Widget.java
package com.company.widgets;

public class Widget {
    String widgetName;
    String widgetType;
    int widgetCode;

    // By making the constructor "protected", can stop arbitrary classes from 
    // constructing and ensure on the WidgetFactory can construct
    protected Widget(String widgetName,
                    String widgetType,
                    int widgetCode) {
         this.widgetName = widgetName;
         this.widgetType = widgetType;
         this.widgetCode = widgetCode;
    }

    public boolean equals(Object other) {
         ...
    }

    public int hashcode() {
         ...
    }

    public void widgetOperation1(String fred) {
        ...
    }

    public String widgetOperation2(int barney ) {
        ...
    }
}

//========================================================

// file WidgetFactory.java
package com.company.widgets;

public class WidgetFactory {
    // Member attributes as needed. E.g. static Set of created Widget objects
    private static Set<Widget> widgetSet;
    static { widgetSet = new HashSet() }

    // 
    public static Widget createNewWidget() {
        Widget widget = new Widget();
        widgetSet.add(widget);
        return widget;
    }

    public static removeWidget(Widget widget) {
        widgetSet.remove(Widget)
    }
}

请注意,1000 个对象并不多,因此此解决方案将是高效的。如果你真的需要优化每一微秒的性能,你可以选择让工厂更智能,这样 Widget 不会被删除,而是被回收——例如你可以有两个 Set,widgetsInUseSet 和 widgetsRecycledSet。

于 2013-02-22T13:30:11.060 回答