Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ember.js/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 计算值在集合中更改的次数_Java_Java Stream - Fatal编程技术网

Java 计算值在集合中更改的次数

Java 计算值在集合中更改的次数,java,java-stream,Java,Java Stream,例如,假设我有一个对象列表 List<Integer> integers = new ArrayList<Integer>() { { add(Integer.valueOf(1)); add(Integer.valueOf(1)); add(Integer.valueOf(2)); // changed add(Inte

例如,假设我有一个对象列表

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
            }
        };
List integers=new ArrayList(){
{
加(整数值(1));
加(整数值(1));
add(Integer.valueOf(2));//已更改
加法(整数。值为(2));
加法(整数。值为(2));
add(Integer.valueOf(3));//已更改
加上(整数值(3));
add(Integer.valueOf(1));//已更改
add(Integer.valueOf(2));//已更改
}
};
上面的示例应该返回数字4,因为该值与前面的数字4次不同

目前,我有一种繁琐且难以维护的方法,它涉及到在项目中循环并跟踪以前的值,以及一个累加器来存储转换的数量

我很想知道是否有一种Java8Streams方法可以解决这个问题,或者是一种比简单地遍历集合并维护前一个值的副本更优雅的解决方案


谢谢

只需将一个元素与前面的元素进行比较:

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);

只需将一个元素与前面的元素进行比较:

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);

是的,可以使用reduce操作。然而,我不会写这样的代码,因为这几乎比迭代解决方案更具可读性。Java流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
  }
静态类ReduceContext{
公开最终整数;
公开最终整数结果;
公共ReduceContext(整数上一个,整数结果){
this.previous=先前;
this.result=结果;
}
}
公共静态void main(字符串[]args){
列表=数组.asList(1,1,2,2,2,3,3,1,2);
ReduceContext reduce=list.stream().reduce(
新的ReduceContext(null,null),
(ctx,当前)->当前等于(ctx.previous)?ctx:
新的ReduceContext(当前,ctx.result!=null?ctx.result+1:0),
(x,y)->新的ReduceContext(null,x.result+y.result));
System.out.println(reduce.result);//打印4
}

诀窍是在上下文中减少,如果先前的值与当前流元素不同,则该上下文将不断更新。此外,这种实现也会因并行缩减而中断,这在合并器上也有一些令人讨厌的边缘情况

是的,可以使用reduce操作。然而,我不会写这样的代码,因为这几乎比迭代解决方案更具可读性。Java流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
  }
静态类ReduceContext{
公开最终整数;
公开最终整数结果;
公共ReduceContext(整数上一个,整数结果){
this.previous=先前;
this.result=结果;
}
}
公共静态void main(字符串[]args){
列表=数组.asList(1,1,2,2,2,3,3,1,2);
ReduceContext reduce=list.stream().reduce(
新的ReduceContext(null,null),
(ctx,当前)->当前等于(ctx.previous)?ctx:
新的ReduceContext(当前,ctx.result!=null?ctx.result+1:0),
(x,y)->新的ReduceContext(null,x.result+y.result));
System.out.println(reduce.result);//打印4
}

诀窍是在上下文中减少,如果先前的值与当前流元素不同,则该上下文将不断更新。此外,这种实现也会因并行缩减而中断,这在合并器上也有一些令人讨厌的边缘情况

如果您必须使用标准列表,这很好,但是如果您想使用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 );

如果您必须使用标准列表,这很好,但是如果您想使用一些Java8,请尝试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 );

不要使用双括号初始化。曾经不要使用双括号初始化。曾经这正是我目前正在做的。我在寻找这个解决方案的替代方案。为什么你认为你需要替代方案?你想优化的是什么?“维护拷贝”这里没有拷贝。它只是对现有对象的引用。“在列表中艰难跋涉”考虑到你需要依次查看每个元素,你可以做的就不多了。如果你想“流化”你的第一个解决方案,你可以做
long count=IntStream.range(0,integers.size()-1)。filter(i->!integers.get(i).equals(integers.get(i+1))).count();
,这是一个等价的方法。(注:我擅自编辑了您的答案,第一段中缺少右括号)。这正是我目前正在做的。我正在寻找此解决方案的替代方案。为什么您认为您需要替代方案?您试图优化的是什么?“维护副本?”“这里没有复制。它只是对现有对象的引用。“在列表中艰难跋涉”因为您需要依次查看每个元素,所以没有什么其他可以做的。如果您想“流化”您的第一个解决方案,您可以执行
long count=IntStream.range(0,integers.size()-1)。filter(i->!integers.get(i).等于(integers.get(i+1))).count();
这将是一个等价项。(注意:我冒昧地编辑了您的答案,第一个代码段中缺少右括号)。我不确定这是不是真的。有一些有状态的
操作,例如
distinct
排序
-它们只是很难编写而已。@BoristheSpider如果输入的顺序像这样起作用