如何在迭代时添加到作为 HashMap 值的 ArrayList?

How to add to an ArrayList that is a HashMap value while iterating?

我有一个 HashMap,键的值是一个 ArrayList。当我逐行读取文件时,我需要添加到属于该特定键的 ArrayList。 该文件可能有 1 行或 100 万行,键名将是行 (String),它的值将表示它在文件中出现的行号。

有人可以帮帮我吗?另外,这种快速的时间复杂性是否明智?如果不是,我该如何优化它?

示例test.txt:

Hello        <== Line 0
Jello        <== Line 1
Mello        <== Line 2
Hello        <== Line 3
Tello        <== Line 4
Jello        <== Line 5
Tello        <== Line 6
Tello        <== Line 7

我需要我的地图存储什么(忽略顺序):

{"Hello": [0, 3]}
{"Jello": [1, 5]}
{"Mello": [2]}
{"Tello": [4, 6, 7]}

我的代码是:

ArrayList<Integer> al = new ArrayList<Integer>();
Map<String, ArrayList<Integer>> hm = new HashMap<String, ArrayList<Integer>>();

int num = 0;
for (String line = file.readLine(); line != null; line = file.readLine()) {
    map.put(line, al.add(num)); <== the issue is here, how to fix?
}

编译器错误:

incompatible types: boolean cannot be converted to ArrayList<Integer>

你的问题是数组上的 add 方法列出了 returns 个布尔值。

您正在尝试做一个 "concordance" 应用程序,在 Java 中很容易在网络上搜索此问题的解决方案。这个问题的其他答案很好地说明了这一点。

关于您的复杂性问题,使用其键是单词且其值是行号数组列表的哈希图非常好(并且应该具有接近最佳的复杂性,因为每个行过程都需要摊销常数时间)。但是,只要一切都适合内存,情况就是如此!如果您的单词文件数量庞大,您可以使用中间文件与一个好的 map-reduce 框架进行索引。

Java 8:

map.computeIfAbsent(line, k -> new ArrayList<>()).add(num);

Java 7:

ArrayList<Integer> values = map.get(line);
if (values == null) {
    map.put(line, values = new ArrayList<>());
}
values.add(num);

ArrayList的add函数returns一个布尔值,表示成功或失败。这就是您收到错误的原因。您必须先将您的号码添加到列表中,然后将列表放入地图中。但是您的代码中存在不同的问题。您将一遍又一遍地向所有键添加相同的列表。

试试这个代码:

Map<String, ArrayList<Integer>> hm = new HashMap<String, ArrayList<Integer>>();
int currentLineNumber = 0;
for (String line = file.readLine(); line != null; line = file.readLine()) {

    if(!hm.containsKey(line))
    {
        hm.put(line, new ArrayList<Integer>());
    }

    hm.get(line).add(currentLineNumber);

    currentLineNumber++;
}

您正在做的是将整数添加到 HashMap 键而不是整个 ArrayList

尝试这样的事情:

            Map<String, ArrayList<Integer>> hm = new HashMap<String, ArrayList<Integer>>();

            String key="";
            while(file.readLine()!=null){
              key=file.readLine();  
      ArrayList<Integer> al = new ArrayList<Integer>();

          OUT: for (String line = file.readLine(); line != null; line = file.readLine()) { 
if(key.equals(line)){
              al.add(num);
  }
    else{
     break OUT;
}
}
             map.put(key, al);
        }

此解决方案尚未经过测试,但我认为它会起作用。

Integer num = 0;
for (String line = file.readLine(); line != null; line = file.readLine()) {

    if(!hm.containsKey(line))
    {
        hm.put(line, new ArrayList<Integer>());
    }

    hm.get(line).add(num);

    num++;
}

我认为这应该可行。