在hashMap中为值添加多个键

时间:2017-05-11 22:15:29

标签: java html hashmap synchronization bufferedreader

我目前以HTML格式提供以下数据:

Year| car type     | # of cars sold
2001| Toyota-Camry | 242435
2000| Honda-Accord | 344423
2001| Honda-Accord | 555255
2000| Honda-Civic  | 342344
2008| Toyota-Prius | 666154
1996| Honda-Accord | 114526
2001| Toyota-Prius | 90234

为了检索这些数据,我有一个BufferedReader来读取HTML中的行。在数据出现之前,我在开头跳过几行,因为有空格。所以我的代码目前是

public class carSales {
    private Map<Integer, HashMap<Integer, String>> carSalesMan = 
            new HashMap <Integer, HashMap<Integer, String>>;

private void getcarTypes(String url) {
    try {
    URL urlz = new URL(url);
    URLConnection urlc = myURL.openConnection();
    BufferedReader line = new BufferedReader
    (new InputStreamReader(urlConnection.getInputStream()));

    String next;
    next = line.readLine(); 

    while (next.contains("</s>") {
        String[] parts = next.split(" ");

        if (carSalesMan.isEmpty() || carSalesMan.get(Integer.parseInt(parts[0])) == null {
            carSalesMan.put(Integer.parseInt(parts[0], new HashMap<Integer, String>());
            carSalesMan.get(Integer.parseInt(parts[0])).put(Integer.parseInt(parts[2]), parts[1])

        }
    }
    catch (IOException e) {
    }
}

这个问题是它似乎只存储具有独特年份的数据。因此我的carSalesMan变量的大小将为4,因为我只有4个唯一年份,当列表中断时它们会相互覆盖。是否有一种简单的方法可以添加所有类型的汽车,即使它在同一年?

3 个答案:

答案 0 :(得分:3)

由于您的if语句,只有一个项目:

    if (carSalesMan.isEmpty() || carSalesMan.get(Integer.parseInt(parts[0])) == null {

您有两种选择,如果您想为每个项目设置不同的插槽,则需要选择@JacobG。回答或者你可以删除这个if语句和用户一个存储项目集合的地图类型作为它的值。你有两种方法可以做第二种选择:

我相信你想要一个MultiValueMap而不是HashMap,它的工作方式几乎与HashMap完全相同,只不过它将值存储在每个键的集合中,而不是每个键只存储一个值。

它不是官方Java,但它是开源的。 您可以在这里找到文档:

http://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/MultiValuedMap.html

或者,您可以使用扩展HashMap<K, V>的自定义类自行实现它,该类包含HashMap<K, Collecton<V>>

答案 1 :(得分:1)

您在此尝试实现的是使用两个单独的键来存储值。使用诸如Guava之类的外部库,这相当于Table<Integer, Integer, String>。如果你不想使用任何外部库,那么在这种情况下使用Map<Integer, Map<Integer, String>>是一个非常好的对象。

您当前代码的问题在于,Map为空或不包含特定年份时,它只会添加信息。您可以将其更改为以下内容,它可以正常工作:

public class carSales {
    private Map<Integer, Map<Integer, String>> carSalesMan = new HashMap<>();

    private void getcarTypes(String url) {
        try {
            URL urlz = new URL(url);
            URLConnection urlc = urlz.openConnection();

            BufferedReader line = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));

            String next = line.readLine(); 

            while (next.contains("</s>") {
                String[] parts = next.split(" ");

                int year = Integer.parseInt(parts[0]);
                int amountSold = Integer.parseInt(parts[2]);
                String model = parts[1];

                carSalesMan.putIfAbsent(year, new HashMap<>());
                carSalesMan.get(year).put(amountSold, model);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

请记住关闭您的连接/阅读器以防止内存泄漏!

编辑:如果您想使用Guava的Table ADT,您可以使用以下内容:

public class carSales {
    private Table<Integer, Integer, String> carSalesMan = HashBasedTable.create();

    private void getcarTypes(String url) {
        try {
            URL urlz = new URL(url);
            URLConnection urlc = urlz.openConnection();

            BufferedReader line = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));

            String next = line.readLine(); 

            while (next.contains("</s>") {
                String[] parts = next.split(" ");

                int year = Integer.parseInt(parts[0]);
                int amountSold = Integer.parseInt(parts[2]);
                String model = parts[1];

                carSalesMan.put(year, amountSold, model);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

答案 2 :(得分:0)

您好我会深入研究Java的库:

&#34; Java Collections Framework没有包含多重映射的界面,因为它们并没有被普遍使用。使用Map的值为List实例的多重映射是一个相当简单的问题。&#34;

来源:https://docs.oracle.com/javase/tutorial/collections/interfaces/map.html