Apologies, this has been done to death but I am really struggling to implement a solution to this problem and I am quite new to Java.
I need to be able to call a method which basically allows a Person object to be added to a list. The method needs to check if that person is already in the list. It needs to perform the check by first name - I know in reality this seems daft but it is something that I need to be able to do in this particular scenario.
The list then needs to be available to the class so a print list of names method can be called later.
The main problem I have encountered whilst trying to implement a solution is a 'ConcurrentModificationException' which is understandable given I have been trying to update the list whilst in the middle of a for each loop.
So, I have come up with the following solution which prevents the 'ConcurrentModificationException' but my solution doesn't work properly and seems overcomplicated - see following code snippet of method:
public void addPerson(Person aPerson) {
// tempPersons list for temporarily storing Person objects
tempPersons = new ArrayList<>();
// if persons list is initially empty, add aPerson object to it
if (persons.isEmpty()) {
persons.add(aPerson);
}
// if persons list is not initially empty
if (!persons.isEmpty()) {
// loop through persons list
for (Person anotherPerson : persons) {
// if persons list anotherPerson first name is the same as the aPerson first name, print message
if (anotherPerson.getFirstName().equals(aPerson.getFirstName())) {
System.out.println("The Person " aPerson.getFirstName()
" is already entered in the list");
}
// otherwise add the aPerson object to the tempPersons list
else {
tempPersons.add(aPerson);
}
}
// once out of loop, add the tempPersons list to the racers list
persons.addAll(tempPersons);
// create new tempPersons2 list based on a hashset of the persons list so there are no duplicates
List<Person> tempPersons2 = new ArrayList<>(
new HashSet<>(persons));
// assign tempPersons2 list without duplicates to persons list
persons = tempPersons2;
}
}
So, if for example I call the above addPerson method 4 separate times with a mixture of unique and duplicate objects (aPerson param), the method correctly identifies that there is already an object with the same first name in there but the persons list always seems to end up with a duplicate object (first name) in there e.g. if I have the following objects:
Person1 FirstName = Bob
Person2 FirstName = Jan
Person3 FirsName = Bob
Person4 FirstName = Ann
Then I make the following method call 4 separate times:
addPerson(Person1);
addPerson(Person2);
addPerson(Person3);
addPerson(Person4);
When I call a print method, I get the following output:
The Person Bob is already entered in the list
Jan
Ann
Bob
Bob
I would expect the following:
The Person Bob is already entered in the list
Jan
Ann
Bob
Apologies for all the waffle and what is probably a really simple solution to most of you but I have been stuck on this for a couple of days. Would appreciate it if anyone could provide a simple solution based on the example I have provided?
Similar article can be found here but I am still struggling.
Adding elements to a collection during iteration
CodePudding user response:
Without changing your code too much:
public void addPerson(Person person) {
// The guard is more or less a premature optimization and should be removed.
if (persons.isEmpty()) {
persons.add(person);
return;
}
for (Person anotherPerson : persons) {
if (anotherPerson.getFirstName().equals(person.getFirstName())) {
System.out.println("The Person " person.getFirstName()
" is already entered in the list");
return;
}
}
persons.add(person);
}
This would exit the method when a match is found, if there are no matches the person
is simply added after the loop. Note the return
in the first check.
Optimizations of this code could be using a Map
or Set
to speed up the contains check; also just using anyMatch on persons
would lead to a more elegant solution.
The duplicates are caused by your
for
loop and it'selse
condition. IfBob
andJan
is in your collection and you add a secondBob
thenJan
won't be equal toBob
and yourelse
path is executed adding a duplicate to your finalpersons
List
.
CodePudding user response:
You can use Set instead of list which will satisfy your need and implement the comparator or comparable interface for person comparison