表示 Java 中大量对象移动的有效方法

Efficient way to represent numerous object move in Java

有盒子和物体。一个对象留在一个盒子里。盒子和物体都有一个唯一的索引,每个物体都有一个权重。

我需要创建一个方法来获取大量订单(> 100 万),您可以在其中看到应该使用出发地和目的地框索引移动多少重量,然后 returns 移动对象集及其目的地。

无需性能思考,非常清晰且易于实现。 (下面为了说明,box index的类型是Long,object是Integer)

public static void main(String[] args) {
    Map<Long, Set<Integer>> objectsInBox = new HashMap<>();
    objectsInBox.put(1l, new HashSet<>(Arrays.asList(1,2,3)));
    objectsInBox.put(2l, new HashSet<>(Arrays.asList(4,5,6)));
    // .... a lot of objects
    Map<Integer, Double> weightsOfObject = new HashMap<>();
    weightsOfObject.put(1, 99.9);
    weightsOfObject.put(2, 23.4);
    // ....

    List<Map<Pair<Long, Long>, Double>> moveOrderList = receiveOrderList();
    getFinalDestinationOfMovingObject(moveOrderList);
}

public static Map<Long, Set<Integer>> getFinalDestinationOfMovingObject(
        List<Map<Pair<Long, Long>, Double>> moveOrderList){
    Map<Long, Set<Integer>> finalDestinationOfObjects = new HashMap<>();
    for(Map<Pair<Long, Long>, Double> moveOrder : moveOrderList){
        // Convert moving amount into object move is not trivial, but given somewhere.
        Map<Integer, Pair<Long,Long>> movingObjects = calculateMovingObjectSet(moveOrder);
        for(Map.Entry<Integer, Pair<Long,Long>> movingObject : movingObjects.entrySet()) {
            int movingObjectIndex = movingObject.getKey();
            long departureIndex = movingObject.getValue().getFirst();
            long destinationIndex = movingObject.getValue().getSecond();
            if(!finalDestinationOfObjects.containsKey(destinationIndex)){
                finalDestinationOfObjects.put(departureIndex, new HashSet<Integer>(Arrays.asList(movingObjectIndex)));
            }else{
                finalDestinationOfObjects.get(departureIndex).add(movingObjectIndex);
            }
            if(!finalDestinationOfObjects.containsKey(departureIndex)){
                // We need just final destination. Remove past object state.
                finalDestinationOfObjects.get(departureIndex).remove(movingObjectIndex);
            }
        }
    }
    return finalDestinationOfObjects;
}

当移动顺序包含大量元素时,需要花费大量时间。我猜这是因为从 HasSet 插入或删除元素效率不高。什么方法更有效?

能不能简单的根据对象来记录最终的目的地,即

finalDestination.put(movingObjectIndex, destinationIndex);

而不是所有复杂的逻辑?这处理了先前目的地存在和不存在的情况。

如果你真的需要finalDestinationOfObjects,你可以在最后创建它,比如

Multimap<Long, Integer> finalDestinationOfObjects = HashMultimap.create();
for (val e : finalDestination.entrySet()) {
    finalDestinationOfObjects.put(e.getValue(), e.getKey());
}

其中 Multimap 来自 Guava(您不需要它,但是 - 与嵌套的 Map 不同 - 它是正确的)。

如果您的对象在盒子之间移动很多,这会更有效率,如果它们通常只移动一次,效率可能会更低。

我建议试一试 post 代码和 CR 上的 calculateMovingObjectSet,更适合此类问题。