2017-03-19 35 views
4

递增有一个表,现在添加一个新的列 - sort_num int default 0如何通过组

id level sort_num 
1 1 0 
2 1 0 
3 2 0 
4 2 0 
5 2 0 
6 3 0 
7 3 0 
8 3 0 
9 3 0 

现在我想设置sort_num值象下面

id level sort_num 
1 1 1 
2 1 2 
3 2 1 
4 2 2 
5 2 3 
6 3 1 
7 3 2 
8 3 3 
9 3 4 

的Java代码实现上述要求是

int sortNum = 0; 
    int currentLevel = fooList.get(0).getLevel(); 
    for (RuleConf foo : fooList) { 
     if(currentLevel != foo.getLevel()){ 
      sortNum = 0; 
      currentLevel = foo.getLevel(); 
     } 
     foo.setSortNum(++sortNum); 
    } 

我想知道,如果Java8可以简化上面的代码?

PS。使用mysql来实现此要求

set @index:=0; update t set sort_num = (@index:[email protected]+1) where level = 1 order by id; 
set @index:=0; update t set sort_num = (@index:[email protected]+1) where level = 2 order by id; 
set @index:=0; update t set sort_num = (@index:[email protected]+1) where level = 3 order by id; 
+1

如果你的意思是'Stream'而不是'Java 8',那么我会说不。因为有些国家依赖于已经看过的元素。 – Flown

回答

2

最好的方法是坚持你的普通增强for循环。我不认为有可能拿出一个单独的Stream解决方案,因为你需要有中间值。像:

Map<Integer, List<RuleConf>> levels = fooList.stream() 
    .collect(Collectors.groupingBy(RuleConf::getLevel)); 
levels.values().forEach(v -> 
    IntStream.range(0, v.size()).forEach(i -> v.get(i).setSortNum(i + 1)) 
); 
0

如果您自己跟踪下一个订单号,您可以使用一个流来完成。该解决方案是线程安全的为好,因此应与平行流工作:

Map<Integer, AtomicInteger> orders = new ConcurrentHashMap<>(); 
fooList.stream().forEachOrdered(foo -> { 
    orders.putIfAbsent(foo.getLevel(), new AtomicInteger()); 
    foo.setOrder(orders.get(foo.getLevel()).incrementAndGet()); 
}); 

应该优于其他流的解决方案,因为它需要唯一的遍历列表。

+0

@Flown:我不明白为什么我提供的解决方案确实依赖于任何订单?是否重要/是否需要考虑'id'? – Harmlezz

+0

因此,我应该将'forEach'换成'forEachOrdered',它可以纠正解决方案,但会牺牲性能(从未请求过)。 – Harmlezz