Reputation:
I have a HashMap and the key's value is an ArrayList. As I read a file line by line I need to add to the ArrayList that belongs to that specific key. The file may have 1 line or 1 million lines, the key name will be the line (String) and it's value will represent the line number that it occurs on in the file.
Can someone help me out? Also, is this fast time-complexity wise? How can I optimize this if it isn't?
Example 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
What I need my map to store (ignore order):
{"Hello": [0, 3]}
{"Jello": [1, 5]}
{"Mello": [2]}
{"Tello": [4, 6, 7]}
My code is:
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?
}
compiler error:
incompatible types: boolean cannot be converted to ArrayList<Integer>
Upvotes: 0
Views: 2164
Reputation: 1209
what you are doing is adding integers to the HashMap key instead of the whole ArrayList
Try something like this:
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);
}
This solution is not been tested but I think this will work.
Upvotes: 0
Reputation: 1838
The add function of ArrayList returns a boolean that represents success or failure. This is why you are getting the error. You will have to add you number to the list first and then put the list in the map. But there is a different problem in your code. You will be adding the same list over and over to all the keys.
Try this code:
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++;
}
Upvotes: 1
Reputation: 1
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++;
}
i think this should work.
Upvotes: 0
Reputation: 88378
Your problem is that the add
method on array lists returns a boolean.
You are trying to do a "concordance" application and it is pretty easy to do a web search for a solution to this in Java. The other answers to this question do a good job of illustrating it.
As to your complexity question, using a hash map whose keys are words and whose values are array lists of line numbers is perfectly fine (and should have near optimal complexity, as each line process takes amortized constant time). This is the case, however, as long as everything fits in memory! If your file of words gets into the gazillions, you can do your concordance with a good map-reduce framework, using intermediate files.
Upvotes: 0
Reputation: 50716
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);
Upvotes: 4