How to Randomize Two Arraylists in the Same Fashion

How to randomize two ArrayLists in the same fashion?

Use Collections.shuffle() twice, with two Random objects initialized with the same seed:

long seed = System.nanoTime();
Collections.shuffle(fileList, new Random(seed));
Collections.shuffle(imgList, new Random(seed));

Using two Random objects with the same seed ensures that both lists will be shuffled in exactly the same way. This allows for two separate collections.

How to randomize two String collections in the same fashion in distributed system?

Many thanks for hashing hint in comments!

I've ended up with re-mapping characters order through pseudo-random hashing (similar to Fisher–Yates shuffle). The rest code was copy-pasted from String.compareTo:

private void magicSort(List<String> list, String seed) {
list.sort(new ShuffleComparator(seed));
}

public class ShuffleComparator implements Comparator<String> {
private static final long MAGIC = 0x5DEECE66DL;
private final String seed;

public ShuffleComparator(String seed) {
this.seed = seed;
}

@Override
public int compare(String s1, String s2) {
int len1 = s1.length();
int len2 = s2.length();
int lim = Math.min(len1, len2);

int seedLen = seed.length();
long random = seed.hashCode();

for (int k = 0; k < lim; k++) {
random = random * MAGIC + seed.charAt(k % seedLen);
char c1 = s1.charAt(k);
char c2 = s2.charAt(k);
if (c1 != c2) {
return ((random % (c1 + 0xFFFF)) & 0xFFFF) -
((random % (c2 + 0xFFFF)) & 0xFFFF) > 0 ? 1 : -1;
}
}
return (random > 0 ? 1 : -1) * (len1 - len2);
}
}

Result:

  • You can keep collections shuffle-sorted at all times
  • Items with identical prefix are grouped together (affinity)
  • The only resource (string seed) is shared between JVMs
  • Negligible impact on performance
  • Zero GC

Examples:

seed: b85a9119-3a98-4491-b503-fc2cfdc344f3
[raccoon George, bird Carry, mice Dr Black, fish Silent, cat Tom, dog Woof]
[bird Frank, mice Dr Black, fish Silent, cat Tom, dog Woof]
[mice Dr Black, fish Silent, cat Tom, dog Woof]

seed: d5378421-d0ea-4b17-80e9-1de6a163bf38
[bird Carry, dog Woof, fish Silent, raccoon George, mice Dr Black, cat Tom]
[bird Frank, dog Woof, fish Silent, mice Dr Black, cat Tom]
[dog Woof, fish Silent, mice Dr Black, cat Tom]

seed: a5f94f60-1207-4f83-9723-bbab5e3b8075
[cat Tom, raccoon George, mice Dr Black, bird Carry, dog Woof, fish Silent]
[cat Tom, mice Dr Black, bird Frank, dog Woof, fish Silent]
[cat Tom, mice Dr Black, dog Woof, fish Silent]

seed: 4b77a61f-c639-42fc-96b2-e1add9f359e9
[bird Carry, raccoon George, cat Tom, mice Dr Black, dog Woof, fish Silent]
[bird Frank, cat Tom, mice Dr Black, dog Woof, fish Silent]
[cat Tom, mice Dr Black, dog Woof, fish Silent]

seed: 2dd78e21-d4ad-4e8a-b139-5d35fe2b0481
[dog Woof, fish Silent, raccoon George, mice Dr Black, bird Carry, cat Tom]
[dog Woof, fish Silent, mice Dr Black, bird Frank, cat Tom]
[dog Woof, fish Silent, mice Dr Black, cat Tom]

Edit #1

For tests I've also implemented hash-based comparator, so would publish it here. Just in case if you don't need affinity (like in my case), but need pure shuffle:

private void magicSort(List<String> list, String seed) {
list.sort(new HashComparator(seed, "SHA-1"));
}

public class HashComparator implements Comparator<String> {
private static final long MAGIC = 0x5DEECE66DL;
private final ThreadLocal<MessageDigest> messageDigest;
private final byte[] seed;
private final int seedHash;

public HashComparator(String seed, String algorithm) {
this.seed = seed.getBytes(ISO_8859_1);
this.seedHash = seed.hashCode();
this.messageDigest = ThreadLocal.withInitial(() -> {
try {
return MessageDigest.getInstance(algorithm);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e.getMessage(), e);
}
});
}

@Override
public int compare(String s1, String s2) {
if (s1.equals(s2)) {
return 0;
}
int diff = getSignature(s1).compareTo(getSignature(s2));
if (diff != 0) {
return diff;
}
long random = seedHash;
random = random * MAGIC + s1.hashCode();
random = random * MAGIC + s2.hashCode();
return ((random & 1) == 0 ? 1 : -1) * s1.compareTo(s2);

}

private ByteBuffer getSignature(String s) {
MessageDigest digest = messageDigest.get();
digest.reset();
digest.update(seed);
for (int i = 0, size = s.length(); i < size; i++) {
char c = s.charAt(i);
digest.update((byte) (c >> 8));
digest.update((byte) c);
}
return ByteBuffer.wrap(digest.digest());
}
}

Result:

  • You can keep collections shuffle-sorted at all times
  • Pure shuffle (no affinity for items with identical prefix)
  • The only resource (string seed) is shared between JVMs

Examples:

8d465fde-9310-4b6c-9709-5cc395deb45e
[raccoon George, mice Dr Black, dog Woof, fish Silent, cat Tom, bird Carry]
[bird Frank, mice Dr Black, dog Woof, fish Silent, cat Tom]
[mice Dr Black, dog Woof, fish Silent, cat Tom]

6daa90dd-f7e7-4615-a45c-fefb0de10c20
[bird Carry, mice Dr Black, fish Silent, cat Tom, dog Woof, raccoon George]
[mice Dr Black, bird Frank, fish Silent, cat Tom, dog Woof]
[mice Dr Black, fish Silent, cat Tom, dog Woof]

9f30b259-c8d1-41f5-8221-40b17cb04260
[cat Tom, mice Dr Black, raccoon George, dog Woof, fish Silent, bird Carry]
[bird Frank, cat Tom, mice Dr Black, dog Woof, fish Silent]
[cat Tom, mice Dr Black, dog Woof, fish Silent]

94b6710f-3232-453d-8009-6d81658b2cca
[dog Woof, fish Silent, bird Carry, cat Tom, mice Dr Black, raccoon George]
[dog Woof, fish Silent, cat Tom, mice Dr Black, bird Frank]
[dog Woof, fish Silent, cat Tom, mice Dr Black]

Two Arraylists have the same elements but in different order, are they equal?

if (INITIAL1.size() == PL1.size() && INITIAL1.containsAll(PL1)) {
//do something
}

Shuffle ArrayList of objects

Hi Sumit i dont know why there are few downvote it is because you have not informed that you are new to Java Language
Please find my answer below

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

final class Product {
private final String name;
private final Double price;
private final Double discount;

Product(String name, Double price, Double discount) {
this.name = name;
this.price = price;
this.discount = discount;
}

@Override
public String toString() {
return "{name=" + name + ", price=" + price + ", discount=" + discount + "}";
}
}

public final class Main {

public static void main(String[] args) {
List<Product> products = new ArrayList<>();
products.add(new Product("Watch", 45.99, 9.99));
products.add(new Product("Keyboard", 21.99, 3.99));
products.add(new Product("Mouse", 99.99, 4.99));

System.out.println("Original items Before shuffle are");
products.forEach(System.out::println);

Collections.shuffle(products);
System.out.println("Original items After shuffle are");
products.forEach(System.out::println);
}
}

How do I obtain the duplicated values of two ArrayLists?

You can use the List#retainAll(Collection<?> c) method, which:

Retains only the elements in this list that are contained in the specified collection (optional operation). In other words, removes from this list all of its elements that are not contained in the specified collection.

List<Point> first = ...
List<Point> second = ...
first.retainAll(second);

Merging two ArrayLists with 2 different objects(which are the instance of the same class)

I came up with the following solution. First get the size of both the arraylists, then increase the capacity(by using ensureCapacity method of ArrayList class) of the arraylist to which the two needs to be merged. Then add the objects of the 2nd arraylist from the last index of the first arraylist.

     a1.add(cls1A);
b1.add(cls1B);
int p = a1.size();

int w = b1.size();

int j = (p + w);

a1.ensureCapacity(j);

for(int r = 0; r <w; r++)
{

ClassA cls1B = new ClassA();
Object obj = b1.get(r);
cls1B = (ClassA)obj;
a1.add(p, cls1B);
p++;
}

How to pass the objects of two arraylists to one another at a specified index

The List interface defines the set(int index, E element) (E = GeometricObject in the present case). Therefore, the four lines you're having trouble with should be rewritten as follows:

a.set(i, data.get(i));
b.set(i - a.size(), data.get(i));
data.set(ai + bi, a.get(ai));
data.set(ai + bi, b.get(bi));

Hope this helps...

Jeff



Related Topics



Leave a reply



Submit