Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/398.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 功能在性能方面的最佳实现_Java_Optimization - Fatal编程技术网

Java 功能在性能方面的最佳实现

Java 功能在性能方面的最佳实现,java,optimization,Java,Optimization,我有一个项目列表和一个地图,其中存储了有关产品及其项目数据的信息。数据库中约有15万个项目,约有20万个产品(每个产品约有1000到2000个对应项目) 我需要一个功能,计数数量的产品,每个项目出现在。这是我已经实现的功能: public Map<Integer, Integer> getProductsNumberForItem(List<Item> itemsList, Map<Integer, Map<Item, Integer>&

我有一个项目列表和一个地图,其中存储了有关产品及其项目数据的信息。数据库中约有15万个项目,约有20万个产品(每个产品约有1000到2000个对应项目)

我需要一个功能,计数数量的产品,每个项目出现在。这是我已经实现的功能:

public Map<Integer, Integer> getProductsNumberForItem(List<Item> itemsList,
        Map<Integer, Map<Item, Integer>> itemsAmount) {
    Map<Integer, Integer> result = new HashMap<>();
    for (Item i : itemsList) {
        int count = 0;
        for (Map<Item, Integer> entry : itemsAmount.values()) {
            if (entry.containsKey(i)) {
                count++;
            }
        }
        result.put(i.getID(), count);
    }
    return result;
}
公共映射GetProductsMemberForItem(列表项列表,
地图项目(Samount){
映射结果=新的HashMap();
用于(项目i:项目列表){
整数计数=0;
for(映射条目:itemsAmount.values()){
if(条目1){
计数++;
}
}
result.put(i.getID(),count);
}
返回结果;
}
它在我的测试数据库上运行得很好,它的数据量很小,但是当我在真实数据上运行它时,它花费了太多的时间(例如:它已经运行了一个小时,但仍然没有完成)。从逻辑的角度来看,我基本上执行了太多的操作,但不确定如何优化

如有任何建议,我们将不胜感激

您有两种方法:

  • 最高效:在数据库中执行的查询中进行计算。
    使用
    count()
    aggregate和
    groupby
    子句,您应该会得到更好的结果,因为整个处理将由专门设计/优化的DBMS执行。

  • 效率较低,但您可以尝试一下:立即检索数据并使用多线程。
    使用Java 8
    parallelStream()
    ,您可能会得到一个可接受的结果,而无需亲自处理同步问题。

    • 您有两种方法:

      • 最高效:在数据库中执行的查询中进行计算。
        使用
        count()
        aggregate和
        groupby
        子句,您应该会得到更好的结果,因为整个处理将由专门设计/优化的DBMS执行。

      • 效率较低,但您可以尝试一下:立即检索数据并使用多线程。
        使用Java 8
        parallelStream()
        ,您可能会得到一个可接受的结果,而无需亲自处理同步问题。


        • 最好的选择是将此计算委托给数据库,避免将所有数据传输到应用程序服务器

          如果这不是一个选项,那么您肯定可以改进当前的算法。现在,对于列表中的每一项,您都在遍历所有产品;这是指数成本

          您可以这样做(使用流,因为在我看来,ressoning更容易遵循,并且允许添加一些改进;但是没有它们也可以实现同样的效果):

          streamproductsitemstream=itemsAmount.values().Stream().flatMap(p->p.keySet().Stream());
          Map countByItemFound=productsitemstream.collect(Collectors.groupingBy(Function.identity(),Collectors.counting());
          Map result=itemsList.stream().collect(Collectors.toMap(Item::getID,i->countByItemFound.getOrDefault(i.getID(),0L.intValue());
          
          使用这种方法,您将对产品项目进行一次完整传递,然后再对项目列表进行另一次传递。这就是线性成本


          具体到streams,您可以尝试启用并行性(将parallelStream添加到我的解决方案中),但并不是完全允许有大的性能提升;这取决于几个因素。我会等待建议的解决方案的性能,如果需要的话,在您的场景中分析有无并行流的性能。

          最好的选择是将此计算委托给数据库,避免将所有数据传输到应用程序远程服务器

          如果这不是一个选项,那么您肯定可以改进当前的算法。现在,对于列表上的每个项目,您都在遍历所有产品;这是指数成本

          您可以这样做(使用流,因为在我看来,ressoning更容易遵循,并且允许添加一些改进;但是没有它们也可以实现同样的效果):

          streamproductsitemstream=itemsAmount.values().Stream().flatMap(p->p.keySet().Stream());
          Map countByItemFound=productsitemstream.collect(Collectors.groupingBy(Function.identity(),Collectors.counting());
          Map result=itemsList.stream().collect(Collectors.toMap(Item::getID,i->countByItemFound.getOrDefault(i.getID(),0L.intValue());
          
          使用这种方法,您将对产品项目进行一次完整传递,然后再对项目列表进行另一次传递。这就是线性成本


          具体到streams,您可以尝试启用并行性(将parallelStream添加到我的解决方案中),但并不是完全允许有大的性能提升;这取决于几个因素。我会等着看建议的解决方案的性能,如果需要的话,在您的场景中分析使用和不使用parallelStream的性能。

          您使用的是关系数据库吗?如果是,那么您应该能够在那里完成大部分工作。推动aggrega对数据库的映射。@mrmcgreg是的,我就是这么想的,我可以只检索映射产品集的大小。@AndrewS它已经存在了。完全忘记了使用适当的映射很容易实现。你使用关系数据库吗?如果是的话,你应该能够在那里完成大部分工作。将聚合推到database.@mrmcgreg是的,我就是这么想的,我可以只检索映射产品集的大小。@AndrewS它已经存在了。完全忘记了使用正确的映射很容易实现。我已经实现了它,只需更正实体内部的映射。谢谢。没问题。但是,如果关系是lazy、 它将对每个产品执行不同的查询。这不是很有效。哦,我没有指定,它是快速加载还是延迟加载。是否可以确定默认情况下的设置方式?默认情况下,
          Stream<Item> productsItemsStream = itemsAmount.values().stream().flatMap(p -> p.keySet().stream());
          Map<Item,Long> countByItemFound = productsItemsStream.collect(Collectors.groupingBy(Function.identity(), Collectors.counting());
          Map<Integer, Integer> result = itemsList.stream().collect(Collectors.toMap(Item::getID, i -> countByItemFound.getOrDefault(i.getID(), 0L).intValue()));