私は独自の解決策を思いつきました。これは主に (他のすべてのメソッドがそれに依存しているため) オーバーライドnext()
しRandom
、一貫性を保つために他のいくつかのものをオーバーライドします。
このメソッドが呼び出されたインスタンスの正確なコピーを提供します (ランダムなインスタンスのコピーを作成することが理にかなっているのかどうかは別のトピックです...^^)。少なくともそれが私の意図でした。
あなたの考えを自由に追加してください!
他の質問はシードの取得に関するものだったのでgetSeed()
、ソリューションにメソッドを簡単に追加できました。またはgetInitialSeed()
、getCurrentSeed()
.
/* Bounded parameter type since a class that implements this interface
* should only be able to create copies of the same type (or a subtype).
*/
public interface Copyable<T extends Copyable<T>>
{
public T copy();
}
public class CopyableRandom extends Random implements Copyable<CopyableRandom>
{
private final AtomicLong seed = new AtomicLong(0L);
private final static long multiplier = 0x5DEECE66DL;
private final static long addend = 0xBL;
private final static long mask = (1L << 48) - 1;
public CopyableRandom() { this(++seedUniquifier + System.nanoTime()); }
private static volatile long seedUniquifier = 8682522807148012L;
public CopyableRandom(long seed) { this.seed.set((seed ^ multiplier) & mask); }
/* copy of superclasses code, as you can seed the seed changes */
@Override
protected int next(int bits)
{
long oldseed, nextseed;
AtomicLong seed_ = this.seed;
do
{
oldseed = seed_.get();
nextseed = (oldseed * multiplier + addend) & mask;
} while (!seed_.compareAndSet(oldseed, nextseed));
return (int) (nextseed >>> (48 - bits));
}
/* necessary to prevent changes to seed that are made in constructor */
@Override
public CopyableRandom copy() { return new CopyableRandom((seed.get() ^ multiplier) & mask); }
public static void main(String[] args)
{
CopyableRandom cr = new CopyableRandom();
/* changes intern state of cr */
for (int i = 0; i < 10; i++)
System.out.println(cr.nextInt(50));
Random copy = cr.copy()
System.out.println("\nTEST: INTEGER\n");
for (int i = 0; i < 10; i++)
System.out.println("CR\t= " + cr.nextInt(50) + "\nCOPY\t= " + copy.nextInt(50) + "\n");
Random anotherCopy = (copy instanceof CopyableRandom) ? ((CopyableRandom) copy).copy() : new Random();
System.out.println("\nTEST: DOUBLE\n");
for (int i = 0; i < 10; i++)
System.out.println("CR\t= " + cr.nextDouble() + "\nA_COPY\t= " + anotherCopy.nextDouble() + "\n");
}
}
そして、ここにメインメソッドの出力があります:
19
23
26
37
41
34
17
28
29
6
TEST: INTEGER
CR = 3
COPY = 3
CR = 18
COPY = 18
CR = 25
COPY = 25
CR = 9
COPY = 9
CR = 24
COPY = 24
CR = 5
COPY = 5
CR = 15
COPY = 15
CR = 5
COPY = 5
CR = 30
COPY = 30
CR = 26
COPY = 26
TEST: DOUBLE
CR = 0.7161924830704971
A_COPY = 0.7161924830704971
CR = 0.06333509362539957
A_COPY = 0.06333509362539957
CR = 0.6340753697524675
A_COPY = 0.6340753697524675
CR = 0.13546677259518425
A_COPY = 0.13546677259518425
CR = 0.37133033932410586
A_COPY = 0.37133033932410586
CR = 0.796277965335522
A_COPY = 0.796277965335522
CR = 0.8610310118615391
A_COPY = 0.8610310118615391
CR = 0.793617231340077
A_COPY = 0.793617231340077
CR = 0.3454111197621874
A_COPY = 0.3454111197621874
CR = 0.25314618087856255
A_COPY = 0.25314618087856255
CopyableRandom と Random を比較するテストもありました。同じ結果が得られました。
long seed = System.nanoTime();
Random cr = new CopyableRandom(seed);
Random cmp = new Random(seed);