使用排序随机播放流 - IllegalArgumentException
Shuffle Stream using sort - IllegalArgumentException
我有这个命令:
list.stream()
.filter(e -> ...)
.sorted(comparatorShuffle())
.findAny()
.orElse(null);
这是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()));
}
};
}
有时我会遇到异常:IllegalArgumentException: Comparison method violates its general contract!
我明白为什么我得到这个,这是因为排序(它是随机的)不遵守规则:if A > B && B > C then A > C
有办法解决suppress/ignore这个错误吗?或者另一种不使用 collect
?
随机播放流的方法
There is a way to suppress/ignore this error?
没有
你并不是真的在洗牌,你表面上只是试图从流中挑选一个随机元素。
为此,您可以将元素与随机数配对并选择 min/max:
...
.map(a -> new AbstractMap.SimpleEntry<>(Math.random(), a))
.min(Map.Entry.comparingByKey())
.map(Map.Entry::getValue)
.orElse(null)
或者,您可以编写一个自定义收集器,在合并时在两个事物之间随机选择:
.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)))
这个替代方案的一个大问题是它没有从流中统一选择(你从流中获得任何一个元素的可能性都不相同),而你使用的是第一种方式。
我有这个命令:
list.stream()
.filter(e -> ...)
.sorted(comparatorShuffle())
.findAny()
.orElse(null);
这是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()));
}
};
}
有时我会遇到异常:IllegalArgumentException: Comparison method violates its general contract!
我明白为什么我得到这个,这是因为排序(它是随机的)不遵守规则:if A > B && B > C then A > C
有办法解决suppress/ignore这个错误吗?或者另一种不使用 collect
?
There is a way to suppress/ignore this error?
没有
你并不是真的在洗牌,你表面上只是试图从流中挑选一个随机元素。
为此,您可以将元素与随机数配对并选择 min/max:
...
.map(a -> new AbstractMap.SimpleEntry<>(Math.random(), a))
.min(Map.Entry.comparingByKey())
.map(Map.Entry::getValue)
.orElse(null)
或者,您可以编写一个自定义收集器,在合并时在两个事物之间随机选择:
.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)))
这个替代方案的一个大问题是它没有从流中统一选择(你从流中获得任何一个元素的可能性都不相同),而你使用的是第一种方式。