我想要洗牌清单。我想这样做的方法是在java 8列表中使用sort方法。 我想为每个数字分配0到1之间的随机数,并根据该数字对列表进行排序。 这就是我拥有和运作的方式:
List<Integer> list = Arrays.asList(1,2,3,4,5);
list.sort(comparing(x->new Random().nextFloat()));
它有效。但是当我想使用这样的参考方法时:
list.sort(comparing(Random::nextFloat));
我得到编译时错误,我不明白为什么。毕竟我的比较器为每个元素生成随机数,然后按此随机数排序。 有什么想法吗?
提前感谢你
答案 0 :(得分:5)
comparing()
方法要求您传递一个Function
Integer
并返回一个排序键,即Float
(或float
在这种情况下。
班级nextFloat()
中的Random
方法不会使用Integer
(或int
)参数,因此对Random::nextFloat
的方法引用不起作用 - 该方法没有预期的签名。
你可以制作一个辅助方法:
public class Example {
private final Random rnd = new Random();
private float nextFloat(int dummy) {
return rnd.nextFloat();
}
public void shuffle() {
List<Integer> list = Arrays.asList(1,2,3,4,5);
list.sort(comparing(this::nextFloat));
}
}
但是还有一个更大的问题。此解决方案没有按照您的想法行事:
我想为每个数字指定0到1之间的随机数,并根据该数字对列表进行排序。
不是为列表中的每个数字指定一个随机数,而是根据该数字进行排序,而是每次调用比较方法时返回一个不同的随机数。您正在使用的排序算法可能会为同一个整数多次调用比较方法。在这种情况下,您每次都会返回一个不同的随机数。
这可能会导致非常奇怪的问题,具体取决于您使用的排序算法。它甚至可能永远不会终止。
正确实施此操作比您想象的要复杂得多。如果这是针对实际应用而不仅仅是练习,请使用Collections.shuffle()
而不是自己实现。
这是一个工作版本:
import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map.Entry;
import java.util.Random;
import java.util.stream.Collectors;
import static java.util.Comparator.comparing;
public final class ShuffleExample {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
// Create a list of Entry objects, which are pairs of a random float
// and a value from the list
Random rnd = new Random();
List<Entry<Float, Integer>> entries = new ArrayList<>();
for (Integer value : list) {
entries.add(new SimpleEntry<>(rnd.nextFloat(), value));
}
// Sort the list of Entry objects by the floats
entries.sort(comparing(Entry::getKey));
// Get the int values out of the sorted list
List<Integer> shuffled = entries.stream()
.map(Entry::getValue)
.collect(Collectors.toList());
System.out.println(shuffled);
}
}