Java 向hashMap中的值添加多个键

Java 向hashMap中的值添加多个键,java,html,hashmap,synchronization,bufferedreader,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 为

我目前有以下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) {
    }
}
公共级汽车销售{
私人地图销售员=
新HashMap;
私有void getcarTypes(字符串url){
试一试{
URL urlz=新URL(URL);
URLConnection urlc=myURL.openConnection();
BufferedReader行=新的BufferedReader
(新的InputStreamReader(urlConnection.getInputStream());
下一个字符串;
next=line.readLine();
while(next.contains(“”){
String[]parts=next.split(“”);
if(carsaller.isEmpty()| | carsaller.get(Integer.parseInt(parts[0]))==null{
put(Integer.parseInt(parts[0],new HashMap());
carsaller.get(Integer.parseInt(部分[0])).put(Integer.parseInt(部分[2]),部分[1]))
}
}
捕获(IOE异常){
}
}

问题是,它似乎只存储具有唯一年份的数据。因此,我的
carsaller
变量的大小将为4,因为我只有4个唯一年份,并且随着列表的下降,它们会相互覆盖。是否有一种简单的方法来添加所有车型,即使是同一年?

只有一项,因为关于你的if声明:

    if (carSalesMan.isEmpty() || carSalesMan.get(Integer.parseInt(parts[0])) == null {
您有两个选项,如果您想为每个项目使用不同的插槽,则需要使用@JacobG.answer,或者您可以删除此if语句,并使用一个映射类型来存储项目集合作为其值。您有两种方法来执行第二个选项:

我相信你想要一个多值映射而不是HashMap。它的工作原理与HashMap几乎完全相同,只是它将每个键的值存储在一个集合中,而不是每个键上只有一个值

它不是正式的Java,但它是开源的。 您可以在此处找到文档:


或者,您也可以使用一个自定义类自己实现它,该类扩展了
HashMap
,封装了
HashMap

,我将深入研究Java的库:

“Java Collections框架不包括多重映射的接口,因为它们并不常用。使用值为列表实例的映射作为多重映射是一件相当简单的事情。”


来源:

您试图实现的是使用两个单独的键来存储值。使用外部库(如Guava),这相当于一个
。如果您不想使用任何外部库,那么在本例中使用
映射
是一个非常好的对象

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

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();
        }
    }
}

是的,
Map
是键到值的唯一映射。您可能需要创建一个对象,该对象包含年份、车型和售出单位(不要忘记
.equals()
.hashcode()
,然后将它们放入一个结构中(可能是一组)并根据需要进行处理。这看起来不像是
Map
的用例。每次添加一个新字段,你注定要不断嵌套越来越多的
Map
。相反,你应该创建一个
Car
类,并使用
列表
集合
@4castle是的,我理解,但不幸的是这是一个项目使用HashMaps和MapsCan的要求您可以详细说明项目的实际要求,因为这可能是一个XY问题。谢谢您的回答!!如果可以,您可以详细说明关闭我的连接和读卡器吗?不客气!当然可以。我不确定您是否关心如何正确关闭连接/读卡器,或者为什么您应该关闭它们,因此如果您可以指定,这将很有帮助。如果您不关闭连接/读卡器,则关联的系统资源将不会释放。不关闭它们是一种不好的做法,因为持续打开连接将由于所需资源不足而导致内存泄漏。我想知道您应该如何操作关闭连接/读卡器。从技术上讲,我不认为
URLConnection
会给您带来任何问题,但是您可以在while循环终止后调用
line.close();
。这是对所问问题的一个很好的回答,但是我认为这句话可能不是真的:“在这种情况下,地图是一个非常好的对象。”。我怀疑是否真的需要按售出汽车的#进行地图查找,而且,如果两款车型在某一年的销售量相同,那么数据就会丢失。不幸的是,从问题中不清楚查找问题需要什么。我不知道如何在我的回答中标记@jacob-g。别担心:)
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();
        }
    }
}