In general making one id from another has issues because you may be clumping two things together which would be easier just to keep separate. Specifically you may be trying to squeeze a foreign key into a primary key when you could just use two keys.
In any case if you really want to build a semi-random primary key from a stub then I would suggest doing it bitwise because that way it'll be easy to extract the original id in SQL and in Java.
As has been mentioned, if you generate a UUID then you don't really need to worry about checking if it's already used, otherwise you probably will want to.
That said the code for making your ids could look like this:
public class IdGenerator {
private SecureRandom random = new SecureRandom();
private long preservedMask;
private long randomMask;
public void init(int preservedBits) {
this.preservedMask = (1L << preservedBits) - 1;
this.randomMask = ~this.preservedMask;
}
public long makeIdFrom(long preserved) {
return (this.random.nextLong() & this.randomMask) | (preserved & this.preservedMask);
}
public UUID makeUuidFrom(long preserved) {
UUID uuid = UUID.randomUUID();
return new UUID(uuid.getMostSignificantBits(), (uuid.getLeastSignificantBits() & this.randomMask) | (preserved & this.preservedMask));
}
public boolean idsMatch(long id1, long id2) {
return (id1 & this.preservedMask) == (id2 & this.preservedMask);
}
}
Essentially this preserves a number of least significant bits in your original. That number you need to specify when you call init.