分组依据,求和然后对事务对象列表进行排序

时间:2019-06-29 14:36:10

标签: list sorting java-8 group-by

我有一天的交易列表,该交易包含以下属性:

Transaction(int transactionID,
                       DateTime transactionDate,
                       String shopId,
                       int productReference,
                       int quantity,
                       float price);

有一个列表List<Transaction>,我想按商店提取销售量最高的100种产品。

因此,我需要按shopId然后按productReference对交易进行分组,然后对数量进行求和,而不是按从销售最多到最少的顺序进行排序。

感谢您的帮助

2 个答案:

答案 0 :(得分:1)

  const sb = this.viewer.getExtension('Autodesk.Section');
  var sectionTool = sb.tool.getSectionBoxValues();

  var sectionbbox = sectionTool.sectionBox;
  const sectionbboxmin = new THREE.Vector3(sectionbbox[0], sectionbbox[1], sectionbbox[3]);      
  const sectionbboxmax = new THREE.Vector3(sectionbbox[4], sectionbbox[5], sectionbbox[6]);

  const sbv1 = new THREE.Vector3(sectionbbox[0], sectionbbox[1], sectionbbox[3]);
  const sbv2 = new THREE.Vector3(sectionbbox[0], sectionbbox[1], sectionbbox[6]);
  const sbv3 = new THREE.Vector3(sectionbbox[0], sectionbbox[5], sectionbbox[6]);
  const sbv4 = new THREE.Vector3(sectionbbox[0], sectionbbox[5], sectionbbox[3]);
  const sbv5 = new THREE.Vector3(sectionbbox[4], sectionbbox[1], sectionbbox[3]);
  const sbv6 = new THREE.Vector3(sectionbbox[4], sectionbbox[1], sectionbbox[6]);
  const sbv7 = new THREE.Vector3(sectionbbox[4], sectionbbox[5], sectionbbox[6]);
  const sbv8 = new THREE.Vector3(sectionbbox[4], sectionbbox[5], sectionbbox[3]);

  var geometry = new THREE.Geometry()

  geometry.vertices = vertices

  geometry.faces = [
    new THREE.Face3(2,1,0),
    new THREE.Face3(0,3,2),
    new THREE.Face3(0,4,7),
    new THREE.Face3(7,3,0),
    new THREE.Face3(2,1,0),
    new THREE.Face3(0,3,2),
    new THREE.Face3(0,1,5),
    new THREE.Face3(5,4,0),
    new THREE.Face3(2,1,0),
    new THREE.Face3(0,3,2),
    new THREE.Face3(1,2,6),
    new THREE.Face3(6,5,1),
    new THREE.Face3(2,1,0),
    new THREE.Face3(0,3,2),
    new THREE.Face3(2,3,7),
    new THREE.Face3(7,6,2),
    new THREE.Face3(2,1,0),
    new THREE.Face3(0,3,2),
    new THREE.Face3(4,5,6),
    new THREE.Face3(6,7,4)
  ]

  const mesh = new THREE.Mesh(geometry, material)
  this.viewer.impl.scene.add(mesh)

因此,您将获得一个以shopId为键的地图,并以数量作为值对交易列表进行排序。 这是预期的行为吗?

答案 1 :(得分:1)

我建议使用其他Product类型,并覆盖equals()hasCode(),这些类型将仅由 shopId 组成和 productReference 。新型将用作输出,这将使所有转换工作更加明显。考虑我的版本,使用 Lombok lib 用法:

import lombok.*;

@Data
@RequiredArgsConstructor(staticName = "of")
@ToString
public class Product {

    final String shopId;
    final int productReference;
}

功能代码本身:

    List<Product> products = transactions.stream()
            // grouping transactions by the same product
            .collect(Collectors.groupingBy(transaction -> Product.of(
                    transaction.getShopId(),
                    transaction.getProductReference())))
            .entrySet().stream()
            // summing all price * quantity occurrences to find top sellings
            .collect(Collectors.toMap(
                    Map.Entry::getKey,
                    e -> e.getValue().stream()
                            .mapToDouble(p -> p.getQuantity() * p.getPrice())
                            .sum()))
            .entrySet().stream()
            // sorting by the most expensive ones at the top, 
            // limiting to 10 and collecting to the list 
            .sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
            .map(Map.Entry::getKey)
            .limit(10)
            .collect(Collectors.toList());