hashmap不能用循环初始化吗?从textfile初始化hashmap

emeijp43  于 2021-06-29  发布在  Java
关注(0)|答案(3)|浏览(365)

我是java的初学者,我正在努力理解hashmaps是如何工作的。我想把它用于我的聊天机器人,这样它就可以识别用户的问题:
例如,key(string)是用户正在询问的内容的类别,value(list)是bot将要查找的问题。
我的问题是,当我在控制台中查看我的输出时,它看起来像是工作的,但是当我调用map.getkey()时,我没有得到我期望的结果。
如果有帮助的话,我使用的是Java1.8。
我有一个文本文件的内容:“!”是类别

!first!
1good
1hello
1bye
!second!
2good
2hello
2bye

这是我的测试类文件,代码如下:

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

public class InitHash
{

    public static void main(String[] args)
    {
        File file = new File(System.getProperty("user.dir") + "/data.txt");

        Map<String, List<String>> map = new HashMap<String, List<String>>();

        try
        {
            Scanner scan = new Scanner(file);
            String key = "";
            List<String> value = new ArrayList<String>();

            while (scan.hasNextLine())
            {
                String line = scan.nextLine();

                if (line.contains("!"))
                {
                    key = line;
                    key = key.replaceAll("!", "");
                    value.clear();
                } else
                {
                    value.add(line);
                }

                System.out.println(key + " , " + value);

                map.put(key, value);
            }

            scan.close();

            System.out.println(map.get("first")); //This prints the second category
            System.out.println(map.get("second"));
        } catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}

这是我在控制台中的输出:

first , []
first , [1good]
first , [1good, 1hello]
first , [1good, 1hello, 1bye]
second , []
second , [2good]
second , [2good, 2hello]
second , [2good, 2hello, 2bye]
[2good, 2hello, 2bye] //This is suppose to output [1good, 1hello, 1bye]
[2good, 2hello, 2bye]

感谢您的帮助和解释,谢谢!

zxlwwiss

zxlwwiss1#

现有的代码可以重写为使用Java8方法 Map::computeIfAbsent 创建 ArrayList 当一个新的键以更简洁的方式出现时。
另外,最好使用 try-with-resources 以确保输入文件的扫描仪自动关闭。

Map<String, List<String>> map = new HashMap<>();
try (Scanner scan = new Scanner(file)) {
    String key = "";

    while (scan.hasNextLine()) {
        String line = scan.nextLine();

        if (line.contains("!")) {
            key = line.replace("!", "");
            map.computeIfAbsent(key, k -> new ArrayList<String>());
        } else {
            map.get(key).add(line);
        }

        System.out.println(key + " , " + map.get(key));
    }

    System.out.println(map.get("first")); //This prints the second category
    System.out.println(map.get("second"));
}

输出:

first , []
first , [1good]
first , [1good, 1hello]
first , [1good, 1hello, 1bye]
second , []
second , [2good]
second , [2good, 2hello]
second , [2good, 2hello, 2bye]
[1good, 1hello, 1bye]
[2good, 2hello, 2bye]
0ejtzxu1

0ejtzxu12#

如注解中所述,您应该使用 ArrayList 每次您确定密钥已更改时,否则您只是重复使用相同的密钥 ArrayList 每把钥匙
下面的示例演示了代码的修改版本,这样,当代码检测到一个新的键,并且前一个键不是空的时,它将Map key 到的当前示例 ArrayList .
然后它将创建一个 ArrayList 把所有的价值观都放进去

File file = new File(System.getProperty("user.dir") + "/data.txt");
Map<String, List<String>> map = new HashMap<String, List<String>>();

try (Scanner scan = new Scanner(file);) {
    String key = "";
    List<String> value = new ArrayList<String>();

    while (scan.hasNextLine()) {
        String line = scan.nextLine();

        if (line.contains("!")) {
            if (!key.trim().isEmpty()) {
                map.put(key, value);
                System.out.println(key + " , " + value);
            }
            key = line;
            key = key.replaceAll("!", "");
            value = new ArrayList<String>();
        } else {
            value.add(line);
        }

    }
    if (!key.trim().isEmpty() && !value.isEmpty()) {
        map.put(key, value);
    }

    scan.close();

    System.out.println(map.get("first")); //This prints the second category
    System.out.println(map.get("second"));
} catch (Exception e) {
    e.printStackTrace();
}
v440hwme

v440hwme3#

在循环中,而不是:

value.clear();

每当您找到一个新的类别时,就初始化它,以便不修改前一个值的内容(因为两个键的列表共享内存地址,所以您只是将最后一个类别的值复制到所有前一个类别)。这将分配 value 添加元素的新地址: value = new ArrayList<String>();

相关问题