'Hashmap values always being overwritten to last looped value
I cannot figure out why my HashMap keeps over writing all of my key/value pairs with the last ip address the method reads. Basically we are meant to store all of the ip addresses of website visitors on a particular day in an arraylist and then append this to a hashmap with the date being the key.
For some reason it keeps overwriting my values with the last value it reads.
Code:
public HashMap<String, String> visitorList(){
HashMap<String, String> allIps = new HashMap<String, String>();
for(LogEntry le : records)
{
String ipAddr = le.getIpAddress();
String date = le.getAccessTime().toString();
allIps.put(date, ipAddr);
}
System.out.println("All visitors: "+allIps);
return allIps;
}
public HashMap<String, ArrayList<String>> iPsForDays(){
ArrayList<String> ipsForDay = new ArrayList<String>();
HashMap<String, ArrayList<String>> visOnDay = new HashMap<String, ArrayList<String>>();
HashMap<String, String> allIps = visitorList();
for(Map.Entry<String, String> entry : allIps.entrySet()){
String key = entry.getKey().substring(4,7)+"-"+entry.getKey().substring(8,10);
String value = entry.getValue();
// visOnDay.put(key, ipsForDay);
ipsForDay.clear();
if(visOnDay.containsKey(key)){
ipsForDay = visOnDay.get(key);
System.out.println("VisOnDay array Value:" +ipsForDay);
ipsForDay.add(value);
System.out.println("+++++++++++++");
System.out.println("Current Values"+ipsForDay);
System.out.println("Current key: "+key);
System.out.println("+++++++++++++");
visOnDay.put(key, ipsForDay);
}
else{
System.out.println("____________");
System.out.println("Current key: "+key);
System.out.println("Currrent value: "+value);
System.out.println("____________");
ipsForDay.add(value);
visOnDay.put(key, ipsForDay);
System.out.println("VisOnDay initialisation: "+ visOnDay);
}
// visOnDay.put(key, ipsForDay);
}
System.out.println("Visitors on relevant days: "+visOnDay);
return visOnDay;
}
The test file we are meant to use is as follows:
84.189.158.117 - - [21/Sep/2015:07:59:14 -0400] "GET /favicon.ico HTTP/1.0" 404 621
84.189.158.117 - - [30/Sep/2015:07:59:14 -0400] "GET /favicon.ico HTTP/1.0" 404 622
61.15.121.171 - - [21/Sep/2015:07:59:21 -0400] "GET /software.html HTTP/1.1" 200 1019
84.133.195.161 - - [14/Sep/2015:07:59:23 -0400] "GET /jflaptmp/ HTTP/1.1" 200 2708
84.133.195.161 - - [21/Sep/2015:07:59:23 -0400] "GET /images/New.gif HTTP/1.1" 200 390
84.133.195.161 - - [21/Sep/2015:07:59:30 -0400] "GET /jflaptmp/may15-2011/withoutSource/JFLAP.jar HTTP/1.1" 200 9781243
61.15.121.171 - - [30/Sep/2015:07:59:46 -0400] "GET /history.html HTTP/1.1" 200 1819
61.15.121.171 - - [30/Sep/2015:08:00:24 -0400] "GET /framebody.html HTTP/1.1" 200 3550
177.4.40.87 - - [30/Sep/2015:08:00:32 -0400] "GET / HTTP/1.1" 200 859
177.4.40.87 - - [30/Sep/2015:08:00:32 -0400] "GET /frameindex.html HTTP/1.1" 200 1127
Additionally the following are custom methods that are including in a file we were given with the homework assignment to assist with parsing files that contain the above data format.
import java.util.*;
public class LogEntry {
private String ipAddress;
private Date accessTime;
private String request;
private int statusCode;
private int bytesReturned;
public LogEntry(String ip, Date time, String req, int status, int bytes) {
ipAddress = ip;
accessTime = time;
request = req;
statusCode = status;
bytesReturned = bytes;
}
public String getIpAddress() {
return ipAddress;
}
public Date getAccessTime() {
return accessTime;
}
public String getRequest() {
return request;
}
public int getStatusCode() {
return statusCode;
}
public int getBytesReturned() {
return bytesReturned;
}
public String toString() {
return ipAddress + " " + accessTime + " " + request
+ " " + statusCode + " " + bytesReturned;
}
}
import java.text.*;
import java.util.*;
public class WebLogParser {
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MMM/yyyy:kk:mm:ss Z", Locale.US);
private static String munchTo(StringBuilder sb, String delim) {
int x = sb.indexOf(delim);
if (x == -1) {
x = sb.length();
}
String ans = sb.substring(0,x);
sb.delete(0, x + delim.length());
return ans;
}
public static LogEntry parseEntry(String line) {
//Assumes line is vald and in this format:
//110.76.104.12 - - [30/Sep/2015:07:47:11 -0400] "GET //favicon.ico HTTP/1.1" 200 3426
StringBuilder sb = new StringBuilder(line);
String ip = munchTo(sb, " ");
munchTo(sb, " "); //ignore -
munchTo(sb, " ["); //ignore -, and eat the leading [
String dateStr = munchTo(sb, "] \""); //]-space is intentional: eat both
Date date = parseDate(dateStr);
String request = munchTo(sb, "\" "); // quote-space is intentional: eat both
String statusStr = munchTo(sb, " ");
int status = Integer.parseInt(statusStr);
String byteStr = munchTo(sb, " ");
int bytes = Integer.parseInt(byteStr);
return new LogEntry(ip, date, request, status, bytes);
}
public static Date parseDate(String dateStr) {
ParsePosition pp = new ParsePosition(0);
return dateFormat.parse(dateStr, pp);
}
}
To clarify the loop itself is not complete as I was trying to figure out why it was overwriting all of the key/values.
Solution 1:[1]
Under iPsForDays()
method inside for(Map.Entry<String, String> entry : allIps.entrySet()){
you are reusing same reference of ipsForDay
for inserting it into map.
Based on your requirement & hashmap declaration, you should create new list if its new key-value pair. For existing key , you have to retrive existing list , add new value into list & then put it back:
for(Map.Entry<String, String> entry : allIps.entrySet()){
String key = entry.getKey().substring(4,7)+"-"+entry.getKey().substring(8,10);
String value = entry.getValue();
if(visOnDay.containsKey(key)){
System.out.println("+++++++++++++");
System.out.println("Current Values"+ipsForDay);
System.out.println("Current key: "+key);
System.out.println("+++++++++++++");
ArrayList<String> existingList=visOnDay.get(key);
existingList.add(value);
visOnDay.put(key, existingList);
}
else{
ArrayList<String> ipsForDay = new ArrayList<String>();
System.out.println("____________");
System.out.println("Current key: "+key);
System.out.println("Currrent value: "+value);
System.out.println("____________");
ipsForDay.add(value);
visOnDay.put(key, ipsForDay);
System.out.println("VisOnDay initialisation: "+ visOnDay);
}
Also, remove ipsForDay
Arraylist declaration which you have done at beginning of method iPsForDays
, that is not required.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |