【问题标题】:Fastest way to restructure a HashMap重组 HashMap 的最快方法
【发布时间】:2011-03-17 04:33:04
【问题描述】:

我有一个 HashMap,可以将公司映射到他们销售的产品的 ArrayList,如下所示:

thiscompany --> [productA, productB...]
thatcompany --> [productC, productA...]

因此,很容易生成特定公司的产品列表。请注意,多家公司可能销售相同的产品。问题是我还需要,给定一个特定的产品,找到所有销售它的公司。并且很快。这种查找可能发生一次或多次。我想知道提供此功能的最有效方法。

目前,我通过遍历每个 ArrayList 并将每个产品映射到其供应商来生成一个新的数据结构。不过这很昂贵,因为我必须在每次添加之前检查我正在创建的 HashMap 是否包含该产品作为键,而且它需要我获取每个 ArrayList,添加新供应商,删除旧的 ArrayList 然后映射每个条目的新条目。不过,我根本看不到更快的方法,也许有人可以为我提供一些见解?

【问题讨论】:

  • 为什么“删除旧的arraylist并映射新的?”您获取现有的。如果为空,则添加一个并添加公司。否则,您检查公司,如果不存在则添加。

标签: java


【解决方案1】:

如何将 ArrayList 更改为 HashSet。

List<String> findCompanies(Map<String,Set<String>> companyToProducts, String product) {
    List<String> companies = new ArrayList<String>();
    for (Map.Entry<String,Set<String>> entry : companyToProducts) {
        Set<String> products = entry.getValue();
        if (products.contains(product)) {
            companies.add(entry.getKey());
        }
    }
    return companies;
}

另一种常见的方法是使用数据库中的表,其中包含产品列和公司列,然后执行以下操作:

select distinct company from companyToProduct where product = 'cheese';

【讨论】:

  • 现在要测试一下,看看它是如何工作的。感谢您的输入。关于数据库替代方案,我实际上看过这个,但产品和公司名称可能会经常更改和/或它们被删除或添加。目前,我将原始 HashMap 存储在对象数据库中,并在用户点击“更新”时替换它。因此,为了在每次更新时保存数据库同步的工作,我会“从 xtable 中删除”并在执行该查询之前重新创建它。但是我不确定该操作需要多长时间,您能否就此提供一些见解?
【解决方案2】:

您为什么不在为公司构建产品地图的同时创建销售产品的公司地图

Map<Product, Set<Company>> companiesByProduct
Map<Company, Set<Product>> productsByCompany

public void add(Company company, Product product) {
    Set<Company> companies = companiesByProduct.get(product);
    if (companies==null) {
        companies = new HashSet<Company>();
        companiesByProduct.put(product, companies);
    }
    companies.add(company);

    // do the same for 
    Set<Product> products = productsByCompany.get(product);
    ....

或者从您可以使用的服务器接收到的地图创建新的 CompaniesByProduct 地图(您可能需要根据原始地图的确切类型进行调整):

for (Company company : originalMap.keySet()) {
  for (Product product : originalMap.get(company)) {
    Set<Company> companies = companiesByProduct.get(product);
    if (companies==null) {
        companies = new HashSet<Company>();
        companiesByProduct.put(product, companies);
    }
    companies.add(company);
   }
}

【讨论】:

  • 一旦你有了它,你可以很容易地获得将产品视为 companyByProduct.get(product) 的公司
  • 不幸的是,我从服务器获得了原始 HashMap,我无法向传输中添加更多数据,我必须完全在客户端创建替代结构。
  • 你能创建一次companyByProduct地图吗(在客户端,而不是每次都搜索原始地图?如果可以,那么你仍然可以使用相同的代码,你只需将其更改为使用来自服务器的原始地图以填充新地图。
  • 是的,这就是我想要做的。问题是我只从 productsbyCompany 地图开始,并且必须从中创建 CompaniesByProduct 地图。我正在寻找最有效的方法来从旧地图填充新地图。
【解决方案3】:

试试MultiMaps.invertFrom

示例:

    Multimap<String, Integer> map = HashMultimap.create();
    map.put("a", 3);
    map.put("a", 4);
    map.put("a", 5);
    map.put("b", 5);
    map.put("b", 3);
    map.put("b", 6);
    Multimap<Integer,String> mapInverse=HashMultimap.create();
    Multimaps.invertFrom(map, mapInverse);
    System.out.println(mapInverse);

输出:

{3=[b, a], 4=[a], 5=[b, a], 6=[b]}

替代解决方案:

在这里,我创建了一个代表公司及其产品的二维布尔数组,以便于查找。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.google.common.collect.TreeMultimap;

public class ProductCompanyMap {
    private Multimap<String, String> companyProducts = TreeMultimap.create();
    private boolean[][] ProductCompanyTable;
    private Map<String,Integer> productIndexMap = new HashMap<String, Integer>();;
    private Map<String,Integer> companyIndexMap = new HashMap<String, Integer>();
    private String[] productArray;
    private String[] companyArray;;


    {
        companyProducts.put("Britania","Biscuts");
        companyProducts.put("Britania","Soap");
        companyProducts.put("Britania","Cloths");
        companyProducts.put("MicroSoft","Software");
        companyProducts.put("Birla","Cloths");
        companyProducts.put("Birla","Software");
    }
    public ProductCompanyMap(){

        Set<String> companyNames=companyProducts.keySet();
        Set<String> productNames= Sets.newTreeSet(companyProducts.values());
        companyArray = companyNames.toArray(new String[companyNames.size()]);
        createIndexMap(companyIndexMap, companyArray);
        productArray = productNames.toArray(new String[productNames.size()]);
        createIndexMap(productIndexMap,productArray);

        ProductCompanyTable = new boolean[companyArray.length][productArray.length];
        for(int i=0;i<companyArray.length;i++)
            for(int j=0;j<productArray.length;j++){
                if(companyProducts.containsEntry(companyArray[i],productArray[j]))
                    ProductCompanyTable[i][j] = true;
            }

    }

    private void createIndexMap(Map<String,Integer> map,String[] arr){
        for(int i=0;i<arr.length;i++)
            map.put(arr[i], i);
    }

    public List<String> getProductsOfCompany(String companyName){
        List<String> productsOfCompany = new ArrayList<String>();
        Integer companyIndex = null;
        if((companyIndex=companyIndexMap.get(companyName))!=null)
        {
            for(int i=0;i<ProductCompanyTable[companyIndex].length;i++)
                if(ProductCompanyTable[companyIndex][i])
                    productsOfCompany.add(productArray[i]);
        }
        return productsOfCompany;
    }
    public List<String> getCompanysWithProduct(String productName){
        List<String> companysWithProduct = new ArrayList<String>();
        Integer productIndex = null;
        if((productIndex=productIndexMap.get(productName))!=null)
        {
            for(int i=0;i<ProductCompanyTable.length;i++)
                if(ProductCompanyTable[i][productIndex])
                    companysWithProduct.add(companyArray[i]);
        }
        return companysWithProduct;
    }
    public static void main(String[] args) {
        ProductCompanyMap mm=new ProductCompanyMap();
        System.out.println("Products of Birla : " +mm.getProductsOfCompany("Birla"));
        System.out.println("Company's producing cloths : "+mm.getCompanysWithProduct("Cloths"));
    }
}

【讨论】:

    【解决方案4】:

    维护两个数据结构——您现在维护的 HashMap 和另一个将产品映射到公司的数据结构:

    productA --> [thiscompany, thatcompany...]
    productC --> [thatcompany, othercompany...]
    

    【讨论】:

    • 是的,这就是我目前正在做的事情。问题是我必须将第一个数据结构转换为第二个数据结构,我正在寻找最有效的方法。
    猜你喜欢
    • 1970-01-01
    • 2018-02-13
    • 2013-08-23
    • 2012-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-22
    • 1970-01-01
    相关资源
    最近更新 更多