I have a program that collects information from the database.
in my previous question i asked about an execption and one of the reponses made me rethink the idea of my loop Link to the old question: ConcurrentModificationExecption
So here is the background i collest alot of information from the database one of the information is the name of the call type that is stored in my Database for example: Mail, Telefon ect. would be different type of contact in formation (which we call, CallQueues)
Since the information that i am extracting is over several days many of the call types will have dublicates. The following is an example of how a row in the database looks like:
ID Name date NoC NoAC
1 Mail 2012-11-27 3 3
Where NoC = number of calls
and NoAC = number of answered calls.
Now to my question.
My original idea was to loop through the list of queues and see if the name reapeared however this would not work as i could not change the list while looping through it. So here is my new idea starting from the while loop, what i want to know is: Is this the best way to avoid dublicates in this situation and if not could you please explain to me how i should do it?
** CODE **
ArrayList<CallQueue> queues = new ArrayList<>();
while (query.next()) {
boolean isNew = true;
if (!queues.isEmpty()) {
for (CallQueue callQueue : queues) {
if (callQueue.getType().equals(query.getString("NAME"))) {
double decimalTime = query.getDouble("DATE");
int hourOfDay = (int)Math.round(24 * decimalTime);
int callAmount = query.getInteger("NoC");
if (hourOfDay > 19) {
hourOfDay = 19;
}
callQueue.addCallsByTime(hourOfDay, callAmount);
isNew = false;
}else {
isNew = true;
}
}
/* Out side the foreach loop, checks if the boolean isNew is true if it is create a new object and insert into the list*/
if (isNew) {
String queueName = query.getString("NAME");
if (!queueName.equalsIgnoreCase("PrivatOverflow")) {
CallQueue cq = new CallQueue(query.getString("NAME"));
double decimalTime = query.getDouble("DATE");
int hourOfDay = (int)Math.round(24 * decimalTime);
int callAmount = query.getInteger("NoC");
if (hourOfDay > 19) {
hourOfDay = 19;
}
cq.addCallsByTime(hourOfDay, callAmount);
queues.add(cq);
}
}
/* if queues is empty which it will be the first time*/
}else {
String queueName = query.getString("NAME");
if (!queueName.equalsIgnoreCase("PrivatOverflow")) {
CallQueue cq = new CallQueue(query.getString("NAME"));
double decimalTime = query.getDouble("DATE");
int hourOfDay = (int)Math.round(24 * decimalTime);
int callAmount = query.getInteger("NoC");
if (hourOfDay > 19) {
hourOfDay = 19;
}
cq.addCallsByTime(hourOfDay, callAmount);
queues.add(cq);
}
}
}
Explanation
Don’t make
queuesanArrayList, make it aHashSetor some other sort ofSet. This will catch duplicates for you in O(1) time instead of O(n). Once you’re done loading the query, you can always take the data out of theHashSetand put it into anArrayListfor future purposes (which has the added advantage of you will know exactly how long to make theArrayList. It would be an O(n) copy, but you’d only have to do it once instead of every time like the other way.To do this correctly, you will probably have to override
CallQueue.hashCode()and.equals(), but that’s easy enough, just return the.hashCode()and.equals()methods of theString namefield.Bug??
By the way, I assumed that
queryis ajava.sql.ResultSet, butResultSetdoesn’t havegetInteger, it hasgetInt. Does your code compile?The Code
Here’s the code, to see what I mean: