【发布时间】:2015-08-27 19:40:00
【问题描述】:
我正在尝试编写一个函数,该函数从集合中随机抽取元素并将它们添加到新集合中。所以如果你想从 {1,2,3,4,5} 中绘制 3 个元素,你可以得到 {5,3,4}。我想出了这个通用函数:
/**
* Take a random sample without repeats of the specified size from a
* collection. Note that if the collection you're sampling from contains
* repeated elements, then the sample could also contain repeated elements.
* Use a Set as an argument to avoid this.
*
* @param <T> The type of objects in the Collection
* @param <E> The type of the collection
* @param collection The collection
* @param size The sample size of elements which you wish to extract from
* the collection
* @param factory A factory method for the collection E. Call with
* "new::ArrayList" or something similar.
* @return A random sample of the collection consisting of 'size' elements
* without repeats (unless the original collection contained repeats).
* @throws IllegalArgumentException if size is larger than the collection.size().
*/
public static <T, E extends Collection<T>> E drawRandomlyWithoutReplacement(List<T> collection, int size, Supplier<E> factory) {
if (size > collection.size()) {
throw new IllegalArgumentException("The sample size cannot be greater than the size of the collection.");
}
E list = factory.get();
for (int i = 0; i < size; i++) {
int r = MathUtils.randomInt(0, collection.size() - 1);
list.add(collection.remove(r));
}
return list;
}
不幸的是,Collection 接口没有一个函数,如果你删除它,它会从集合中返回一个元素,但是 List 和 Vector(以及其他)确实有它。有没有办法让这个函数适用于列表和向量,而不必重载 3 次?我尝试将第一个参数设为 C 类型,其中 C extends List<T> | Vector<T> 但不幸的是这不起作用。
【问题讨论】:
-
Set是哪个? -
您的 JavaDoc 说:“使用 Set 作为参数来避免这种 [重复]”。所以没有必要创建不同的方法还是我错了?
-
@DraganBozanovic,你说得对,Set 没有这个方法。
-
A
Vectoris-aList...!? -
请解释为什么将
E extends Collection更改为E extends List应该不能解决您的问题