我有这个命令:
list.stream()
.filter(e -> ...)
.sorted(comparatorShuffle())
.findAny()
.orElse(null);
Run Code Online (Sandbox Code Playgroud)
这是comparatorShuffle():
public static <E> Comparator<E> comparatorShuffle(){
return new Comparator<>(){
private final List<Integer> temp = List.of(-1, 1);
private final Random random = new Random();
@Override
@SuppressWarnings("ComparatorMethodParameterNotUsed")
public int compare(E o1, E o2){
return temp.get(random.nextInt(temp.size()));
}
};
}
Run Code Online (Sandbox Code Playgroud)
有时我会遇到异常:IllegalArgumentException: Comparison method violates its general contract!
我明白为什么我得到这个,这是因为排序(它是随机的)不遵守规则:if A > B && B > C then A > C
有办法抑制/忽略这个错误吗?或者不使用的另一种方式来随机播放流collect?
有办法抑制/忽略这个错误吗?
不。
你并不是真的在这里洗牌,表面上你只是想从流中选择一个随机元素。
为此,您可以将元素与随机数配对并选择最小值/最大值:
...
.map(a -> new AbstractMap.SimpleEntry<>(Math.random(), a))
.min(Map.Entry.comparingByKey())
.map(Map.Entry::getValue)
.orElse(null)
Run Code Online (Sandbox Code Playgroud)
或者,您可以编写一个自定义收集器,在合并时在两个事物之间随机选择:
.collect(
Collector.of(
// Use Optional.empty() as the identity element, if the stream is empty.
Optional::empty,
// Optionalize the element, taking it randomly or if we have the identity element.
(a, b) -> a.isEmpty() || Math.random() > 0.5 ? Optional.of(b) : a,
// Merge.
(a, b) -> Math.random() > 0.5 ? b : a,
// Unwrap the value.
r -> r.orElse(null)))
Run Code Online (Sandbox Code Playgroud)
这种替代方案的一个大问题是,它没有从流中统一选取(您从流中获取任何一个元素的可能性并不相同),而您使用的是第一种方式。
| 归档时间: |
|
| 查看次数: |
201 次 |
| 最近记录: |