2

Java で不透明なハンドルを実装したいと考えています。

つまり、ユーザーが Factory の種類のクラスで Create を呼び出すと、クラスのオブジェクトが作成されますが、オブジェクト自体は返されず、クラスのインスタンスを表す int が返されます。HashMapint をキーとして、オブジェクトを値として格納する があります。クラスの他のすべてのメソッドは、1 つのパラメーターとして int を取り、からオブジェクトを取得HashMapし、対応するオブジェクトに対して必要な操作を実行します。HashMapから削除し、ガベージ コレクションを許可するremove メソッドがあります。

コードのハンドル部分を実装する必要がないようにする既存のクラス/データ構造があるかどうか疑問に思っていましたか?

hashCodeoridentityHashCodeは一意であることが保証されていないため、一意の識別子として使用できるとは思いません。

実行中のカウンターを自分で実装する場合、一意の ID を作成する際のスレッド セーフ、オブジェクトをオブジェクトから削除する際の ID の再利用などの問題を処理する必要がありますhashMap。これに役立つ既存のクラスがあるかどうか疑問に思っていました.

4

4 に答える 4

1

id として long 値を取ります。ロングが不足することはありません。int を使用すると、複雑さが増し、速度が低下します。
syncronized (またはプライベート ロック オブジェクト) を使用して get() set() および increment() を記述するのは簡単です。それ以外の場合AtomicLongincrementAndGet()

于 2013-02-17T12:20:24.500 に答える
1

簡単な計算をしてみましょう。最大 10000 個のオブジェクト、最大 1 時間のライブタイムがあると言いました。1 分間に 10000 個のオブジェクトという、より厳しい条件を想定してみましょう。32 ビット整数は、約 1 年間で十分です。さらに、整数がオーバーフローしても、1 年前に使用された整数を再利用して、ゼロから開始します。私が見る限り、それで十分です。したがって、AtomicInteger を使用するだけで、非常に高速に動作し、要件を十分に満たすことができます。

それでも疑問がある場合は、より回復力のある解決策を用意できます。新しいハンドルが生成されたら、最初に HashMap にこのキーが既にあるかどうかを確認します (これは非常に高速な操作です)。ある場合は、次の整数を選択してください。これは、オペレーティング システムで生成されたhttps://superuser.com/questions/135007/how-are-pids-に似ています。

于 2013-02-22T11:47:11.397 に答える
1

私は自分のカウンターを保持します。スレッドの安全性が心配な場合は、AtomicIntegerを使用してください。

また、ID を再利用しようとはしません。これにより、デバッグとログ記録が非常に困難になります。整数が不足することはまずありません。

于 2013-02-15T10:45:53.123 に答える
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 個のオブジェクトは多くないため、このソリューションはパフォーマンスに優れていることに注意してください。マイクロ秒ごとのパフォーマンスを本当に最適化する必要がある場合は、ウィジェットを削除せずに再利用するようにファクトリをよりスマートにするオプションがあります。

于 2013-02-22T13:30:11.060 に答える