Reputation: 39
I need to join two Collection<String>
, get n random elements and remove them from the original collection in which they are stored.
To join the collections I thought about iterate them and store in an custom map structure in a way to:
Is there a simple method to do that?
Can you help me?
Upvotes: 0
Views: 178
Reputation: 7179
How about this:
Collection<String> collection1 = new ArrayList<String>();
Collection<String> collection2 = new ArrayList<String>();
List<String> allElements = new ArrayList<String>(collection1);
allElements.addAll(collection2);
Collections.shuffle(allElements);
Random random = new Random();
int n = 10;
List<String> randomResults = new ArrayList<String>(n);
for (int i = 0; i < n && !allElements.isEmpty(); i++) {
String randomElement = allElements.remove(random.nextInt(allElements.size()));
randomResults.add(randomElement);
}
collection1.removeAll(randomResults);
collection2.removeAll(randomResults);
Upvotes: 1
Reputation: 948
Does the following work for you?
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
public class Combiner {
private static final Random rnd = new Random();
public static void main(String[] args) {
Collection<String> boys = Sets.newHashSet("James", "John", "andrew",
"peter");
Collection<String> girls = Sets.newHashSet("mary", "jane", "rose",
"danny");
// Combine the two
Iterable<String> humans = Iterables.concat(boys, girls);
// Get n Random elements from the mix
int n = 2;
Collection<String> removed = randomSample4(humans, n);
// Remove from the original Collections
Iterables.removeAll(boys, removed);
Iterables.removeAll(girls, removed);
// or even
boys.removeAll(removed);
girls.removeAll(removed);
// And now we check if all is well
System.out.println(boys);
System.out.println(girls);
}
public static <T> Collection<T> randomSample4(Iterable<T> humans, int m) {
List<T> sample = Lists.newArrayList(humans);
Set<T> res = new HashSet<T>(m);
int n = sample.size();
for (int i = n - m; i < n; i++) {
int pos = rnd.nextInt(i + 1);
T item = sample.get(pos);
if (res.contains(item))
res.add(sample.get(i));
else
res.add(item);
}
return res;
}
}
The randomSample4 method has been copied from this blog.
Upvotes: 0
Reputation: 4324
Interesting you want to use the map for that. I would suggest using a MultiMap
(Google's Guava
for example). It allows you to hold a key and then a Collection
of values, all belonging to that key. So, you would have only two keys (corresponding to your original Collections
).
Another solution would be to just add all Collections
into a third a Collection
(there is an addAll(Collection c)
method available). Provided, there are no duplicate values, you can check if a certain item from the third collection is part of any of your other two while iterating.
These are kind of rudimentary ways to achieve whatever your question asked, but worth a try.
Hope these pointers help a bit!
Upvotes: 0