如何基于比较连续的列表元素将Java流减少为布尔值
作为一个重构练习,我尝试采取如下方式:如何基于比较连续的列表元素将Java流减少为布尔值,java,functional-programming,reduce,collectors,Java,Functional Programming,Reduce,Collectors,作为一个重构练习,我尝试采取如下方式: for (int i = 1; i < orderedList.size(); i++) { Object object1 = ordered.get(i - 1); Object object2 = ordered.get(i); if (isDifferent(object1, object2)) return true; } return false; for(int
for (int i = 1; i < orderedList.size(); i++) {
Object object1 = ordered.get(i - 1);
Object object2 = ordered.get(i);
if (isDifferent(object1, object2)) return true;
}
return false;
for(int i=1;i
转换为一个简单的Java函数语句。乍一看,我是按顺序处理列表中的元素,所以reduce()
听起来很有希望,但是
Optional
或另一个list
作为包装器,以便跟踪我是否有差异感谢您提供此思考练习的帮助。因为您正在使用for循环索引两个
列表
s,您可以将其替换为,并使用以下内容减少:
虽然,我并不认为这有什么好处,因此将其作为for循环可能更具可读性。这里的基本操作称为“压缩”:给定两个
a
s和B
s流以及一个组合运算符(a,B)->C
,您可以创建C
流(截短到较短的输入流)。假设您有这样一个函数
<A, B, C> Stream<C> zip
(Stream<? extends A> as, Stream<? extends B> bs,
BiFunction<? super A, ? super B, ? extends C> combine);
标准库中没有zip
。如果您使用的是像Guava这样的东西,您可以检查它是否有此操作,例如..或者,您可以自己实现它并将其粘贴到某个实用程序类中,此时您可能需要。我将重现此处列出的代码(这似乎是从实际Streams API的测试版复制而来):
publicstaticstreamzip(Stream从您的逻辑来看,它不是这么简单吗
return orderedList.stream.distinct().count() != 1; // assuming that you have equals and
// hashcode method overridden for
// your object.
流适合孤立地处理每个元素,或者减少时处理相邻元素。您可以“滥用”模式是通过读取/写入流外的变量来实现的,但在这一点上,你最好使用一个老式的循环。离开它有什么不对?流将剥夺你短路的可能性。因此,从性能角度看,你在流中的表现会更差,除非isDifferent
计算结果为true
exce非常罕见。就可读性而言,你已经看到它的效果不好。@Bohemian Reduce并没有定义为处理相邻元素的操作;它需要关联函数,因此可能会处理,例如(a×b)×(c×d)
,这不适合OP的任务。您必须将所有元素映射到包含间隔(第一个和最后一个元素)和布尔状态的类型。除此之外,您还将失去短路……事实上,我有点喜欢这样。我正试图摆脱“I-1”使用reduce操作,当我在一个forEach
中插入i+1/i-1时,它看起来比原来的更糟糕,但即使使用手动索引,它也更可读。没有想过将同一个列表压缩到自身中,也没有意识到任何(相对)标准库支持zip。谢谢!
zip(ordered.stream(), ordered.stream().skip(1), this::isDifferent).anyMatch(x -> x);
// ordered: a b c d ... y z
// skipped: b c d ... y z
// zipped : (a, b) (b, c) (c, d) ... (y, z)
public static<A, B, C> Stream<C> zip(Stream<? extends A> a,
Stream<? extends B> b,
BiFunction<? super A, ? super B, ? extends C> zipper) {
Objects.requireNonNull(zipper);
Spliterator<? extends A> aSpliterator = Objects.requireNonNull(a).spliterator();
Spliterator<? extends B> bSpliterator = Objects.requireNonNull(b).spliterator();
// Zipping looses DISTINCT and SORTED characteristics
int characteristics = aSpliterator.characteristics() & bSpliterator.characteristics() &
~(Spliterator.DISTINCT | Spliterator.SORTED);
long zipSize = ((characteristics & Spliterator.SIZED) != 0)
? Math.min(aSpliterator.getExactSizeIfKnown(), bSpliterator.getExactSizeIfKnown())
: -1;
Iterator<A> aIterator = Spliterators.iterator(aSpliterator);
Iterator<B> bIterator = Spliterators.iterator(bSpliterator);
Iterator<C> cIterator = new Iterator<C>() {
@Override
public boolean hasNext() {
return aIterator.hasNext() && bIterator.hasNext();
}
@Override
public C next() {
return zipper.apply(aIterator.next(), bIterator.next());
}
};
Spliterator<C> split = Spliterators.spliterator(cIterator, zipSize, characteristics);
return (a.isParallel() || b.isParallel())
? StreamSupport.stream(split, true)
: StreamSupport.stream(split, false);
}
return orderedList.stream.distinct().count() != 1; // assuming that you have equals and
// hashcode method overridden for
// your object.