请教一个 Java8 stream 应用问题

42 天前
 Curiosity777
请问各位大佬 Java8 能实现阶段累加吗

比如以下表
id 当前值 累计值
10 7.66 928.09
9 6.56 920.43
8 4.79 913.87
7 6.23 909.08

当前的累计=当前值+前一次累计

例:
id10 的累计值=10 的当前值+9 的累计值

大佬们 stream 能实现吗,想半天没想出来,求指教
1971 次点击
所在节点    Java
20 条回复
lu5je0
42 天前
reduce
wweerrgtc
42 天前
Curiosity777
42 天前
@lu5je0 reduce 最后结果就是一个了
palytoxin
42 天前
reduce
ZGame
42 天前
楼上正解,Op 可以去了解下 c# linq 的操作符,或者 js 相关的。 然后用 gpt 翻译 java 有惊喜= =
NelsonZhao
42 天前
没必要强行用 stream ,用 for 循环自己处理呗
Habyss
42 天前
创建一个临时值存就可以了呀
```java
// 临时累加值
AtomicReference<Double> cumulative = new AtomicReference<>(0.0);

// 使用流进行累计值计算
return data.stream()
// 排序
.sorted(Comparator.comparingInt(DataItem::getId))
// 看你情况是源对象处理还是返回新的对象
.peek(item -> {
// 累加
cumulative.updateAndGet(v -> v + item.getCurrentValue());
// 设置当前累计值
item.setCumulativeValue(cumulative.get());
})
.collect(Collectors.toList());

```
liumao
42 天前
巧了,上个月才做了这个需求,没必要非要用流,容易绕进去。
cpstar
42 天前
看了 7 楼,徒增编译器压力和代码阅读压力,…(⊙_⊙;)…
piecezzz
42 天前
static class Test{

public Test(Integer id,float cur,float total){
this.id = id;
this.curVal = cur;
this.totalVal = total;
}

public Integer id;
public float curVal;
public float totalVal;

}

public static void main(String[] args) {
Test one = new Test(10,7.66f,928.09f);
Test two = new Test(9,6.56f,920.43f);
Test three = new Test(8,4.79f,913.87f);
Test four = new Test(7,6.23f,909.08f);

Stream.of(one,two,three,four).sorted(Comparator.comparing(t -> t.id))
.reduce((prev, cur) -> {
cur.totalVal += prev.curVal;
return cur;
});
System.out.println(one.totalVal);
}
ocean1477
42 天前
mysql 的情况下 sql 也可以啊
select id, cur_val + lag(acc_val, 1, 0) over (order by id) as sum_val from test order by id desc;
java8 的话也行
```java
MyObj obj1 = new MyObj(10, 7.66, 928.09, 0.0);
MyObj obj2 = new MyObj(9, 6.56, 920.43, 0.0);
MyObj obj3 = new MyObj(8, 4.79, 913.87, 0.0);
MyObj obj4 = new MyObj(7, 6.23, 909.08, 0.0);
List<MyObj> list = Lists.newArrayList(obj4, obj3, obj2, obj1);
MyObj res = list.stream().reduce(new MyObj(0, 0.0, 0.0, 0.0), (prev, curr) -> {
curr.setSumVal(prev.getAccVal() + curr.getCurVal());
return curr;
}, (a, b) -> a);
list.forEach(System.out::println);
```
Karte
42 天前
```java
public class StreamTest {


private List<C> initialSequence() {
var res = new ArrayList<C>();

var rand = new Random(0);
for (int i = 0; i < 10; i++) {
C c = new C();
c.setId(i);
c.setCurrent(rand.nextInt(1000));
res.add(c);
}

return res;
}

@Test
public void stream() {
List<C> sequence = initialSequence();
System.out.println("before");
output(sequence);


C finalResult = sequence.stream().reduce(new C(), (pre, now) -> {
Integer accumulative = Optional.ofNullable(pre.getAccumulative()).orElse(0);
now.setAccumulative(accumulative + now.getCurrent());
return now;
});


System.out.println("after");
output(sequence);
}

private void output(List<C> sequence) {
for (C c : sequence) {
System.out.println(String.format("id: %s, acc: %d", c.getId(), c.getAccumulative()));
}
}

static class C {

private Integer id;

private Integer accumulative;

private Integer current;

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public Integer getAccumulative() {
return accumulative;
}

public void setAccumulative(Integer accumulative) {
this.accumulative = accumulative;
}

public Integer getCurrent() {
return current;
}

public void setCurrent(Integer current) {
this.current = current;
}
}

}
```

无视 reduce 的结果即可.
nitmali
42 天前
fori 能解决 没必要强求...
netabare
42 天前
reduce 里面可以是一个列表。当然 java 没有模式匹配写起来比较恶心。
misdake
42 天前
这种东西应该是实现一个能够累加的迭代器,输出一个累加值(还可以提供当前值)的流
Ashe007
42 天前
以 ID 为 key ,累加值为 value 的 map 来解决这个问题,无论是 for 还是 stream 都很简单,不熟练先用 for 实现,让 ai 改成 stream 实现不就好了吗?
Leviathann
42 天前
不就是 scan 吗

或者 reduce 成一个 list

`10 7.66 928.09
9 6.56 920.43
8 4.79 913.87
7 6.23 909.08`
.split('\n')
.reverse()
.map(line => line.split(' '))
.map(([id, value, accu]) => ({
id: Number(id),
value: Number(value),
accu: Number(accu)
}))
.reduce((result, cur) => {
const last = result[result.length - 1]
if (last) {
result.push({...cur, accu: last.accu + cur.value})
} else {
result.push(cur)
}
return result
}, [])
msg7086
42 天前
map+reduce 一般用在可以并行处理的场景里。
你这里是顺序累加,不能乱序执行,不能并行,不如直接一个 for 循环搞定。
S4msara
41 天前
不非要用 Stream 实现的话可以参考:

```java
public List<Record> greeting(List<Record> list) {
ListIterator<Record> iterator = list.listIterator();
while (iterator.hasNext()) {
Double preTotal = null;
if (iterator.previousIndex() != -1) {
Record previous = iterator.previous();
preTotal = previous.getTotal();
iterator.next();
}
Record next = iterator.next();
if (preTotal != null) {
next.setTotal(preTotal + next.getCurr());
}
iterator.set(next);
}
return list;
}
```
siweipancc
32 天前
不要用流,遵循无状态设计必定新增中间类,撸下来性能跟内存消耗远大于常规写法

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1030662

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX