Reputation: 20565
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);
}
}
}
Upvotes: 0
Views: 102
Reputation: 32343
Don't make queues
an ArrayList
, make it a HashSet
or some other sort of Set
. 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 the HashSet
and put it into an ArrayList
for future purposes (which has the added advantage of you will know exactly how long to make the ArrayList
. 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 the String name
field.
By the way, I assumed that query
is a java.sql.ResultSet
, but ResultSet
doesn't have getInteger
, it has getInt
. Does your code compile?
Here's the code, to see what I mean:
HashMap<String, CallQueue> queues = new HashMap<String, CallQueue>();
while (query.next()) {
if (!queues.isEmpty()) {
if (queues.containsKey(query.getString("NAME"))) {
CallQueue oldQueue = queues.get(query.getString("NAME"));
double decimalTime = query.getDouble("DATE");
int hourOfDay = (int)Math.round(24 * decimalTime);
int callAmount = query.getInt("NoC");
if (hourOfDay > 19) {
hourOfDay = 19;
}
oldQueue.addCallsByTime(hourOfDay, callAmount);
} 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.getInt("NoC");
if (hourOfDay > 19) {
hourOfDay = 19;
}
cq.addCallsByTime(hourOfDay, callAmount);
queues.put(query.getString("NAME"), cq);
}
}
}
}
// you could return this if you just want a collection...
Collection<CallQueue> values = queues.values();
// Or this if you MUST have an ArrayList...
return new ArrayList(values);
Upvotes: 2