0

I wrote a Predicate code that takes any Object and tests it for the following conditions:

  1. if Object type is String and contains "k" then it should return true.
  2. if Object type is Integer and greater than 100 then it should return true.
  3. if Object type is Employee which is class and having salary of employee greater than 60000, it should return true.

After writing that Predicate method I wrote the remove method that removes values from list according to Predicate method.

public class ConditionalRemove {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<String>(Arrays.asList("ramesh", "kushal", "suresh", "kc"));
        System.out.println(conditionalRemove(list));
    }

    public static <T> List<T> conditionalRemove(ArrayList<T> list) {
        ConditionCheck<T> cond = new ConditionCheck<>();
        for (T t : list) {
            if (cond.test(t)) {
                list.remove(t);
            }
        }
        return list;
    }

    static class ConditionCheck<T> implements Predicate<T> {
        @Override
        public boolean test(T t) {
            if (t instanceof String) {
                return (((String) t).contains("k"));
            } else if (t instanceof Integer) {
                return ((int) t > 100);
            } else if (t instanceof Employee) {
                return ((int) ((Employee) t).getSalary() < 60000);
            }
            return true;
        }
    }
}

After compiling this code I found Exception in thread "main" java.util.ConcurrentModificationException

ericbn
  • 10,163
  • 3
  • 47
  • 55
Ramesh KC
  • 570
  • 7
  • 30
  • You are deleting from the list while you are iterating it (in `conditionalRemove()`. To fix, make a copy of the list and iterate that. – nbokmans Oct 25 '16 at 22:10
  • @nbokmans - Not necessary - just use Iterator explicitly. – PM 77-1 Oct 25 '16 at 22:13
  • 1
    Possible duplicate of [Iterating through a Collection, avoiding ConcurrentModificationException when removing in loop](http://stackoverflow.com/questions/223918/iterating-through-a-collection-avoiding-concurrentmodificationexception-when-re) – PM 77-1 Oct 25 '16 at 22:15

4 Answers4

2

The issue is you are updating the list when you are iterating over that. The issue can be fixed by updating code as

public static <T> List<T> conditionalRemove(ArrayList<T> list) {
        ConditionCheck<T> cond = new ConditionCheck<>();
        Iterator it = list.iterator();
        while(it.hasNext())     
        {
            it.next();
            if (cond.test(t)) {
                it.remove();
            }
         }
        return list;
    }
kushagra mittal
  • 343
  • 5
  • 17
2

Since you're using Java 8, a functional approach would be to create a new filtered list:

public static <T> List<T> conditionalRemove(ArrayList<T> list) {
    return list.stream()
            .filter(new ConditionCheck<>())
            .collect(Collectors.toList());
}

You can even replace the static inner class by just a method:

public static <T> List<T> conditionalRemove(ArrayList<T> list) {
    return list.stream()
            .filter(ConditionalRemove::test)
            .collect(Collectors.toList());
}

private static <T> boolean test(T t) {
    // your predicate implementation...
}
ericbn
  • 10,163
  • 3
  • 47
  • 55
2

Don't reinvent the wheel: Use Collection#removeIf():

public static <T> List<T> conditionalRemove(ArrayList<T> list) {
    list.removeIf(new ConditionCheck<>());
    return list;
}

At one line, this is hardly worth the effort of creating a method to call... just make the single line call in-line:

public static void main(String[] args) {
    List<String> list = new ArrayList<>(Arrays.asList("ramesh", "kushal", "suresh", "kc"));
    list.removeIf(new ConditionCheck<>());
    System.out.println(list);
}
Bohemian
  • 412,405
  • 93
  • 575
  • 722
1

Some data structures throws the java.util.ConcurrentModificationException when you modify them during an iteration, in order to do that with success you need use a synchronized structure such as "CopyOnWriteArrayList", this is the java doc reference

Hope this can help you!

Regards.