Getting java.util.ConcurrentModificationException in Iterator - java

I am trying to iterate custom object using iterator and adding data into that custom object but when size of object is 1 it's working but when I am adding second data it gives me an error : nested exception is java.util.ConcurrentModificationException
My Code is as Follow :
public List<ValidationObject> _validationObjects = new ArrayList<>();
public void addError(String key, String value){
int size = _validationObjects.size();
if(size==0){
ValidationObject vo = new ValidationObject();
vo.setKey(key);
vo.addLine(value);
_validationObjects.add(vo);
}
else{
Iterator i = _validationObjects.iterator();
while(i.hasNext()){
ValidationObject obj = (ValidationObject)i.next();
if(obj.getKey().equals(key)){
obj.addLine(value);
}else{
ValidationObject vo = new ValidationObject();
vo.setKey(key);
vo.addLine(value);
_validationObjects.add(vo);
}
}
}
}
In class ValidatioObject I have variable as follow :
private List<String> _lines;
private String _key;
I am calling addError() method as follow :
list.addError("Name", "Should not empty");
list.addError("Prefix", "Should not empty");
Any Help on it, why it's behaving like this.

I think you need to change the logic. Add to your list outside the iterator
else{
boolean keyFound = false;
Iterator i = _validationObjects.iterator();
while(i.hasNext()){
ValidationObject obj = (ValidationObject)i.next();
if(obj.getKey().equals(key)){
obj.addLine(value);
keyFound = true;
}
}
if(!keyFound){
ValidationObject vo = new ValidationObject();
vo.setKey(key);
vo.addLine(value);
_validationObjects.add(vo);
}
}

Why this exception is because of this line,
_validationObjects.add(vo);
beacuse,
If the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException.
So try adding that using the iterator instance only.
Define a ListIterator and add to that,
ListIterator i=_validationObjects.listIterator();
i.add(vo);

Related

How do I get Object out of HashMap?

Im trying to get an object out of a HashMap and call a method from this object.
But insted of getting the object, I get a normal java.lang.Object.
public void setExits(HashMap<Direction, Exit> e){
this.exits = e;
Iterator it = e.entrySet().iterator();
while (it.hasNext()) {
Map.Entry exits = (Map.Entry) it.next();
Exit r = exits.getValue(); //HERE I GET ERROR
}
}
You are declaring type constraints in the method signature but in the method body you are not taking any advantage of using the type constraints.
What you are doing is similar to you are using HashMap< Object, Object >. That is why compile error.
Correct Code:
public void setExits(HashMap<Direction, Exit> e){
this.exits = e;
Iterator<Map.Entry<Direction, Exit>> it = e.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<Direction, Exit> entry = it.next();
Exit r = entry.getValue(); // OK
}
}
Change this line:
Iterator it = e.entrySet().iterator();
to:
Iterator<Entry<Direction, Exit>> it = e.entrySet().iterator();
Here is how I might iterate every value in a HashMap
HashMap<Directive, Exit> tempHashMap = new HashMap<>();
for(Directive directive:tempHashMap.keySet()){
Exit tempExit = tempHashMap.get(directive);
//do what you want with the exit
}
You are using a HashMap like a list. It's not a very effective list.
Instead do
Object value = map.get(key);
And it will skip the items that aren't under the key, very efficiently.
public void setExits(HashMap<Direction, Exit> exits, Direction direction){
this.exits = e.get(direction);
}
What you have missed is the generics for the Map.Entry.
It looks to me as though you are trying to loop over all the entries of the map, you might find a for loop easier.
for(Map.Entry<Direction, Exit> entry : e.entrySet()) {
Direction dir = entry.value();
//do stuff
}

What is the best approach to split an Arraylist based on their values

I would like to split an ArrayList that I am looping trough and set a field called active which can be true or false. But at the end of loop I would like to split this collection in two groups.. active = false and active = true, so doing this I won't need to search in database twice..
for example:
private List<Classes> searchClasses(ClassItems listItems) {
List<ClassItem> items = new ArrayList<ClassItem>();
for (Iterator<ClassItem> iterator = listItems.getItems().iterator(); iterator.hasNext();) {
ClassItems item = iterator.next();
ClassEntityManager classEnt = ClassEntityManager.search(item.getId);
if(classEnt.active()){
item.setActive(true);
items.add(item);
}
}
return items;
}
What is the best approach to do this??
Make two lists instead of one.
if(classEnt.active()) {
activeItems.add(item);
item.setActive(true);
} else {
inactiveItems.add(item);
}
Use two collections, one for actives and the other for not actives.
When you fetch the data from the DB, simply put the CalssItem in the correct list:
private List<ClassItem> searchClasses(ClassItems listItems) {
List<ClassItem> activeItems= new ArrayList<ClassItem>();
List<ClassItem> notActiveItems= new ArrayList<ClassItem>();
Iterator<ClassItem> i = listItems.getItems().iterator();
while(i.hasNext()) { //This is a better approach.
ClassEntityManager classEnt = ClassEntityManager.search(i.next().getId);
if(classEnt.active()){
item.setActive(true);
activeItems.add(item);
}else{
item.setActive(false);
notActiveItems.add(item);
}
}
List<ClassItem> ret = new ArrayList<ClassItem>(activeItems);
ret.addAll(notActiveItems);
return ret;
}
BUT, in this way, both activeItems and notActiveItems are unreacheable. Best thing to do is to have a loop outside your method that checks if the ClassItem is active or not. In this way both activeItems and notActiveItems can be deleted from the method:
private List<ClassItem> searchClasses(ClassItems listItems) {
List<ClassItem> items= new ArrayList<ClassItem>();
Iterator<ClassItem> i = listItems.getItems().iterator();
while(i.hasNext()) { //This is a better approach.
ClassEntityManager classEnt = ClassEntityManager.search(i.next().getId);
item.setActive(classEnt.active());
items.add(item);
}
return items;
}
And to use the list:
List<ClassItem> items = searchClasses(classItems);
for(ClassItem item: items){
if(item.isActive()){
//do something
}else{
//do something else
}
}
Better yet is to use the magnificient and beautiful Java 8 Stream API:
List<ClassItem> active = items.stream().filter(x->x.isActive).collect(Collectors.toList());
List<ClassItem> notActive = items.stream().filter(x->!x.isActive).collect(Collectors.toList());
or the one liner:
List<ClassItem> active = searchClasses(classItems).stream().filter(x->x.isActive).collect(Collectors.toList());
NOTES:
Your code has a return type of List<Classes>, while the returned value is of List<ClassItem>. Which is right?
Your iterator has a generic type of ClassItem while the next() method returns a ClassItems object. Which is right?

Some times java.util.ConcurrentModificationException thrown

I executing below code but some times i got java.util.ConcurrentModificationException exception..But some times working fine.please let me know where i did wrong code.Below is my code please check my logic also if there is any better way then let me know.
public String saveSkills(HttpServletRequest request,#RequestParam String skills,#RequestParam String Email) throws IOException
{
Domain domain1 = (Domain)request.getSession().getAttribute("Domain");
Long domanId =domain1.getDomainId();
System.out.println(skills);
String[] skillsParts = skills.split(",");
UserProfile user = userProfileManager.getUserByEmail(domain1.getPrimary_Domain_Id(), Email);
if(user.getSkillsList().size()>0){
Iterator it = user.getSkillsList().iterator();
while (it.hasNext())
{
Skills skillsitereator = (Skills) it.next();
int count=0;
for(int i =0;i<skillsParts.length;i++){
if((skillsParts)[i].equals(skillsitereator.getSkillName())){
break;
}else{
count++;
}
}
if(count == skillsParts.length){
it.remove();
userProfileManager.update(user);
}
}
}else{
for(int i =0;i<skillsParts.length;i++){
Skills skillObj = new Skills();
skillObj.setSkillName(skillsParts[i]);
user.getSkillsList().add(skillObj);
}
userProfileManager.update(user);
}
skillsParts = skills.split(",");
System.out.println(skillsParts);
ArrayList<Integer> values =new ArrayList<Integer>();
for(int i =0;i<skillsParts.length;i++){
Iterator it = user.getSkillsList().iterator();
while (it.hasNext())
{
Skills skillsitereator = (Skills) it.next();
if((skillsParts)[i].trim().equals(skillsitereator.getSkillName().trim())){
break;
}
else{
Skills skillObj = new Skills();
skillObj.setSkillName(skillsParts[i]);
user.getSkillsList().add(skillObj);
userProfileManager.update(user);
}
}
}
Gson gson = new Gson();
return gson.toJson(user);
}
This is from the JavaDoc for ConcurrentModificationException:
For example, if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will throw this exception.
In your last loop, you sometimes do
user.getSkillsList().add(skillObj);
while iterating using user.getSkillsList().iterator().
ConcurrentModificationExceptions happen when modifying a Collection while iterating it, other than using the Iterator.remove() method.
So, it will be thrown when executing:
user.getSkillsList().add(skillObj);
From the Java Tutorials, The Collection interface :
Note that Iterator.remove is the only safe way to modify a collection during iteration; the behavior is unspecified if the underlying collection is modified in any other way while the iteration is in progress.

what is causing my NoSuchElementException for ArrayList

I know that there are lots of threads on NoSuchElementException in Java here but I still cannot figure out what is going on here
I am trying to come up with a solution for Transitive Dependencies Kata 18 which is posted at http://codekata.pragprog.com/2007/01/kata_eighteen_t.html
dependencies_for method is supposed to take in a char item and compute all dependencies for the item. The exception occurs when I try to add an element to finalDependencies ArrayList
This is the place where my NullPointerException occurs. I have traced all of these data structures and none of them have a Null value. I don't understand what is causing my exception here. Please see my code:
public class Test_Dependencies
{
public static void main(String[] args) {
Dependencies Dep = new Dependencies();
Dep.add_direct('A', "B C");
Dep.add_direct('B', "C D");
Dep.dependencies_for('A');
}
}
public class Dependencies {
HashMap dependenciesList;
public Dependencies()
{
HashMap<Character, ArrayList> dependenciesList = new HashMap<Character, ArrayList>();
}
public void add_direct(char mainItem, String dependentItems)
{
// code that works here
}
public String dependencies_for(char item)
{
ArrayList finalDependencies = new ArrayList<Character>();
Character key = new Character(item);
//get initial dependencies for the item and add them
ArrayList processingDependencies = dependenciesList.get(key);
Iterator itr = processingDependencies.iterator();
while(itr.hasNext())
{
if(finalDependencies.contains(itr.next()) == false && itr.next() != key)
{
// NoSuchElement exception here
finalDependencies.add(itr.next());
// look again at each item in dependenciesList. If it is in the list then add it to processingDependencies
if(dependenciesList.containsKey(itr.next()) && !processingDependencies.contains(itr.next()))
{
processingDependencies.add(itr.next());
}
}
}
// turn finalDependencies into a string
itr = finalDependencies.iterator();
String allDependencies = "";
while(itr.hasNext())
{
allDependencies = allDependencies + " " + itr.next();
}
return allDependencies;
}
}
I am a bit perprlexed because processingDependencies and finalDependencies ArrayLists are not null. And processingDependencies arraylist contains an item
You are calling twice. The first call is "protected" by a matching hasNext Call. The second is not. Save the result of next into a temporary variable and use that, instead of using the value directly, since every call to next will try to advance the iterator first. In the good case, you get an exception. In the bad case, things seem to work, but your program is dealing with the wrong value.
You can't do this:
while(itr.hasNext())
{
if(finalDependencies.contains(itr.next()) == false && itr.next() != key)
{
// NoSuchElement exception here
finalDependencies.add(itr.next());
// stuff removed
}
}
You must verify that iter.hasNext() is true prior to each call of itr.next(). What happens when you reach the last item in itr, but then call itr.next() three times?
Answer: NoSuchElementException. Check out Iterator
The problem is here:
HashMap dependenciesList;
public Dependencies()
{
HashMap<Character, ArrayList> dependenciesList = new HashMap<Character, ArrayList>();
}
You declare a hashmap called dependenciesList. You then try to instantiate that list, but what you actually do is create a local variable named the same thing. They are two separate variables. Then you try to use the one that hasn't been instantiated here:
ArrayList processingDependencies = dependenciesList.get(key);
What you need to do is instantiate the first dependenciesList instead of creating a new one
(I'm not a pro at java, but something like dependenciesList = new HashMap....() instead of HashMap<..> dependenciesList = new HashMap...() )

How do I remove an object from an ArrayList in Java?

I have an ArrayList that contains some object, such as User, and each object has a name and password property. How can I delete only the User object that has a specific 'name' from this ArrayList?
Iterator<User> it = list.iterator();
while (it.hasNext()) {
User user = it.next();
if (user.getName().equals("John Doe")) {
it.remove();
}
}
You could use something like this:
// If you are using java 8
userList.removeIf(user-> user.getName().equals("yourUserName"));
// With older version
User userToRemove = null;
for(User usr:userList) {
if(usr.getName().equals("yourUserName")) {
userToRemove = usr;
break;
}
}
userList.remove(userToRemove);
Another thought: If User class can be uniquely defined by the username and if you override equals with something like:
public boolean equals(Object arg0) {
return this.name.equals(((user) arg0).name);
}
You can remove the User without iterating through the list . You can just do :
list.remove(new User("John Doe"))
You are probably faced with the ConcurrentModificationException while trying to remove object from the List. An explanation for this exception is that the iterator of the ArrayList is a fail-fast iterator. For example, it will throw an exception (fail) when it detects that its collection in the runtime has been modified. The solution to this problem is to use the Iterator.
Here is a simple example that demonstrate how you could iterate through the List and remove the element when specific condition is met:
List<User> list = new ...
for (Iterator<User> it = list.iterator(); it.hasNext(); ) {
User user = it.next();
if (user.getUserEmail().equals(currentUser.getUserEmail())) {
it.remove();
}
}
Recommended way to solve this problem is:
ArrayList<User> list = new ArrayList<User>();
list.add(new User("user1","password1"));
list.add(new User("user2","password2"));
list.add(new User("user3","password3"));
list.add(new User("user4","password4"));
Iterator<String> iter = list.iterator();
while (iter.hasNext())
{
User user = iter.next();
if(user.name.equals("user1"))
{
//Use iterator to remove this User object.
iter.remove();
}
}
Using Iterator to remove an object is more efficient than removing by simply typing ArrayList(Object)
because it is more faster and 20% more time saving and a standard Java practice for Java Collections.
You could:
loop over the list with an iterator
check if each item in your list is the right user (checking the name)
if it is, use the remove method of the iterator.
Just search through the ArrayList of objects you get from the user, and test for a name equal to the name you want to remove. Then remove that object from the list.
Your code might look like this:
List<User> users = new ArrayList<User>();
public void removeUser(String name){
for(User user:users){
if(user.name.equals(name)){
users.remove(user);
}
}
}
ArrayList<User> userList=new ArrayList<>();
//load data
public void removeUser(String userName){
for (User user: userList){
if(user.getName()equals(userName)){
userList.remove(user);
}
}
}

Categories

Resources