java8流对聚合总和进行分组和排序

时间:2015-06-09 13:13:31

标签: java-8 grouping aggregate java-stream

给出一个java类Something

class Something {
  private int parentKey;
  private String parentName;
  private int childKey;
  private int noThings;

  public Something(int parentKey, String parentName, int childKey, 
    int noThings) {
    this.parentKey = parentKey;
    this.parentName = parentName;
    this.childKey = childKey;
    this.noThings = noThings;
  }

  public int getParentKey() {
    return this.parentKey;
  }

  public int getNoThings() {
    return this.noThings;
  }
}

我有一些对象列表

List<Something> somethings = newArrayList(
            new Something(425, "Lemon", 44, 23),
            new Something(123, "Orange", 125, 66),
            new Something(425, "Lemon", 11, 62),
            new Something(123, "Orange", 126, 32),
            new Something(323, "Lime", 25, 101),
            new Something(123, "Orange", 124, 88)
);

我希望能够对它们进行排序,以便按每个父对象的noThings和noThings的累积总和对它们进行排序。

所以我最终得到了

List<Something> sortedSomethings = newArrayList(
            new Something(123, "Orange", 124, 88),
            new Something(123, "Orange", 125, 66),
            new Something(123, "Orange", 126, 32),
            new Something(323, "Lime", 25, 101),
            new Something(425, "Lemon", 11, 62),
            new Something(425, "Lemon", 44, 23)
);

我知道用parentKey映射它,noThings的总和是

Map<Integer, Integer> totalNoThings = colns
            .stream()
            .collect(
                    Collectors.groupingBy(
                            Something::getParentKey,
            Collectors.summingInt(ClientCollectionsReceived::getNoThings)));

我认为可能包装我的Something类并且每个父键的总数可能会有效。

class SomethingWrapper {
  private int totalNoThingsPerClient;
  private Something something;
}

但它似乎很多工作而且不是很优雅。

非常感谢任何观察/想法。

2 个答案:

答案 0 :(得分:2)

嗯,您已经通过收集汇总信息完成了主要工作

Map<Integer, Integer> totalNoThings = somethings.stream()
    .collect(Collectors.groupingBy(Something::getParentKey,
        Collectors.summingInt(Something::getNoThings)));

然后您需要做的就是在排序操作中使用这些信息:

List<Something> sorted=somethings.stream().sorted(
    Comparator.comparing((Something x)->totalNoThings.get(x.getParentKey()))
          .thenComparing(Something::getNoThings).reversed())
    .collect(Collectors.toList());

答案 1 :(得分:0)

实际上不得不做一个小调整,而不是totalNoThings.get,它是totalNothings.indexOf

所以最终解决了。是

List<Integer> totalNoThings
    = somethings.stream()
    .collect(Collectors.groupingBy(Something::getParentKey,
                    Collectors.summingInt(Something::getNoThings)))
    .entrySet().stream()
    .sorted(Map.Entry.comparingByValue())
    .map(Map.Entry::getKey)
    .collect(Collectors.toList());


List<Something> sorted 
    = somethings.stream().sorted(
            Comparator.comparing(
            (Something obj)->totalNoThings.indexOf(
            obj.getParentKey()))
    .thenComparing(Something::getNoThings).reversed())
            .collect(Collectors.toList());