例如,假设我有一个对象列表
List<Integer> integers = new ArrayList<Integer>() {
{
add(Integer.valueOf(1));
add(Integer.valueOf(1));
add(Integer.valueOf(2)); // changed
add(Integer.valueOf(2));
add(Integer.valueOf(2));
add(Integer.valueOf(3)); // changed
add(Integer.valueOf(3));
add(Integer.valueOf(1)); // changed
add(Integer.valueOf(2)); // changed
}
};
上面的例子应该返回数字4,因为该值与之前的数字不同4次。
我目前有一种繁琐且难以维护的方式,包括循环遍历项目并跟踪先前的值和累加器以存储转换次数。
我很想知道是否有一种java 8流方式来解决这个问题,或者是一个更优雅的解决方案,而不仅仅是跋涉整个集合并维护前一个值的副本。
谢谢!
答案 0 :(得分:3)
只需将元素与前一个元素进行比较:
int count = 0;
for (int i = 1; i < integers.size(); ++i) {
if (!integers.get(i).equals(integers.get(i-1))) {
++count;
}
}
System.out.println(count);
或使用Iterator
:
int count = 0;
if (!integers.isEmpty()) {
Iterator<?> it = integers.iterator();
Object prev = it.next();
while (it.hasNext()) {
Object curr = it.next();
if (!curr.equals(prev)) {
++count;
}
prev = curr;
}
}
System.out.println(count);
答案 1 :(得分:0)
是的,可以使用reduce操作。但是,我不会编写这样的代码,因为这比迭代解决方案更难读。 Java Stream API并非设计为跨元素的操作,因此不要使用此代码。
static class ReduceContext {
public final Integer previous;
public final Integer result;
public ReduceContext(Integer previous, Integer result) {
this.previous = previous;
this.result = result;
}
}
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 1, 2, 2, 2, 3, 3, 1, 2);
ReduceContext reduction = list.stream().reduce(
new ReduceContext(null, null),
(ctx, current) -> current.equals(ctx.previous) ? ctx :
new ReduceContext(current, ctx.result != null ? ctx.result + 1 : 0),
(x, y) -> new ReduceContext(null, x.result + y.result));
System.out.println(reduction.result); // prints 4
}
如果前一个值与当前的流元素不同,那么诀窍就是减少不断更新的上下文。此实现也将通过并行缩减来打破,并且在合并器上也存在一些令人讨厌的边缘情况。
答案 2 :(得分:0)
如果你必须使用一个标准的列表,但是如果你想使用一些Java 8,请尝试使用ObservableList。通过下面的示例,我没有将其设置为能够一次添加整个值列表,而是一次添加一个值。
ObservableList<Integer> list = FXCollections.observableArrayList();
list.addListener((ListChangeListener.Change<? extends Integer> c) -> {
while( c.next() ) {
if( c.wasAdded() ) {
// Make sure the list is not equal to 1, or you'll compare a null and get an error
// Then get the added sub list (the new value you're adding) and compare it to the second to last
if( c.getList().size() > 1 && c.getAddedSubList().get(0) != c.getList().get( c.getTo()-2 ) ) {
System.out.println( "Change!" );
}
}
}
});
list.add( 1 );
list.add( 1 );
list.add( 2 );
list.add( 3 );
list.add( 1 );
list.add( 2 );
list.add( 3 );
list.add( 3 );
输出:
Change!
Change!
Change!
Change!
Change!