2

Please I'm not good in english and a beginner in programming so please be patient with me.

Please see my code first so you will understand better what I'm having trouble with.

I have created an object named ObjAbc.java:

package exer;

public class ObjAbc {
    private Integer code;
    private Integer value;

    public ObjAbc () {

    }

    public ObjAbc (Integer code, Integer value) {
            this.code = code;
            this.value = value;
    }

    public Integer getCode() {
            return code;
    }

    public void setCode(Integer code) {
            this.code = code;
    }

    public Integer getValue() {
            return value;
    }

    public void setValue(Integer value) {
            this.value = value;
    }

    @Override
    public String toString() {
           return "ObjAbc [code=" + code + ", value=" + value + "]";
    }
}

Then I have a class ObjAbcTest.java

package exer;

import java.util.ArrayList;
import java.util.List;

public class ObjAbcTest {

    public static List<ObjAbc> populateList() {
        List<ObjAbc> objAbcs = new ArrayList<ObjAbc>();
        objAbcs.add(new ObjAbc(1, 11));
        objAbcs.add(new ObjAbc(2, 25));
        objAbcs.add(new ObjAbc(3, 125));
        objAbcs.add(new ObjAbc(4, 73));
        objAbcs.add(new ObjAbc(5, 12));
        objAbcs.add(new ObjAbc(1, 12));
        objAbcs.add(new ObjAbc(3, 1));
        return objAbcs;
    }

    public static void main(String[] args) {
        List<ObjAbc> list = populateList();
        List<ObjAbc> newList = new ArrayList<ObjAbc>();
        for (ObjAbc o : list) {
            if (!newList.isEmpty()) {
                for (ObjAbc n : newList) {
                    if (o.getCode().intValue() == n.getCode().intValue()) {
                        n.setValue(n.getValue() + o.getValue());
                        break;
                    } 
                    else {
                        newList.add(o);
                    }
                }
            } 
            else {
                newList.add(o);
            }
        }

        for (ObjAbc n : newList) 
            System.out.println(n.toString());
    }
}

What Im trying to do is to sum all the values of all ObjAbc that have the same code but remove the other ObjAbc after I summed up the values which means the object must be displayed once but the values should be the total.

Example:

Input:

ObjAbc [code=1, value=11]
ObjAbc [code=2, value=25]
ObjAbc [code=3, value=125]
ObjAbc [code=4, value=73]
ObjAbc [code=5, value=12]
ObjAbc [code=1, value=12]
ObjAbc [code=3, value=1]

Expected output:

ObjAbc [code=1, value=23]
ObjAbc [code=2, value=25]
ObjAbc [code=3, value=126]
ObjAbc [code=4, value=73]
ObjAbc [code=5, value=12]

But what I get is:

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
    at java.util.AbstractList$Itr.next(AbstractList.java:343)
    at exer.ObjAbcTest.main(ObjAbcTest.java:25)
Adi Inbar
  • 12,097
  • 13
  • 56
  • 69
TokiMucho
  • 23
  • 3
  • You cannot add something to a list being iterated over (here `newList`) –  Sep 23 '13 at 05:05
  • Please post the ObjAbcTest.java also. There might be the case where you are iterating over a collection and modifying it also. http://docs.oracle.com/javase/7/docs/api/java/util/ConcurrentModificationException.html – Jaydeep Patel Sep 23 '13 at 05:07
  • @JaydeepPatel I have included it just now. Please see the updated code. – TokiMucho Sep 23 '13 at 05:08

5 Answers5

2

This should works (not tested).

public class ObjAbcTest {

    public static List<ObjAbc> populateList() {
            // same as yours
    }

    public static void main(final String[] args) {
        final List<ObjAbc> list = populateList();
        final Map<Integer, Integer> sums = new HashMap<Integer, Integer>();

        // compute sums
        for (final ObjAbc obj: list) {
            // this if can be simplified with ? operator
            if (sums.containsKey(obj.getCode())) {
                sums.put(obj.getCode(), sums.get(obj.getCode()) + obj.getValue());
            } else {
                sums.put(obj.getCode(), obj.getValue());
            }
        }

        // populates newList
        final List<ObjAbc> newList = new ArrayList<ObjAbc>();
        for (final Map.Entry<Integer, Integer> e : sums.entrySet()) {
            newList.add(new ObjAbc(e.getKey(), e.getValue()));
        }

        // TODO: sort?

        // outputs
        for (final ObjAbc n : newList) 
            System.out.println(n.toString());
        }
}

Here we are using a Map (code => sum) to store the sums.

  • Im having Can only iterate over an array or an instance of java.lang.Iterable in the for loop of sums... Im confused. – TokiMucho Sep 23 '13 at 05:26
  • Sorry there was two mistake (parenthesis missing and `sums.entrySet()`). Now it compiles and runs –  Sep 23 '13 at 05:30
  • I got it. I should place sums.entrySet... Thanks... Please updated your answer. Ill be accepting this one. – TokiMucho Sep 23 '13 at 05:36
1

You're modifying newList via

 newList.add() 

while iterating on the list:

 for (ObjAbc n : newList)

Which invalidates the iterator.

You could, for instance, use ListIterator, which allows you to modify the list while iterating. E.g.:

 ListIterator<ObjAbc> li = newList.listIterator();
 while (li.hasNext()) {
    ObjAbc n = li.next();
    if (...) 
    else {
      li.add(...)
    }
 }
James
  • 8,512
  • 1
  • 26
  • 28
0

for each loop in Java uses an implicit iterator. And ArrayList's iterator is fail-fast by design. It throws a ConcurrentModificationException as soon as it detects change in underlying structure (list).

Basically, the list has "modified" now and the iterator corresponds to list's previous state. Runtime detects this and throws exception.

Read here on how to handle such cases.

Community
  • 1
  • 1
rocketboy
  • 9,573
  • 2
  • 34
  • 36
0
newList.add(o);

While iterating over collection you cannot modify it.

That is the issue while adding.

What you can do is simply take another list and add items to it.

Suresh Atta
  • 120,458
  • 37
  • 198
  • 307
0

I fixed your code, problem is with the add in the second loop, is incorrect, as you try to add the new value if it doesn't match the first element in the newList.

this should work: package exer;

import java.util.ArrayList;
import java.util.List;

public class ObjAbcTest {

    public static List<ObjAbc> populateList() {
        List<ObjAbc> objAbcs = new ArrayList<ObjAbc>();
        objAbcs.add(new ObjAbc(1, 11));
        objAbcs.add(new ObjAbc(2, 25));
        objAbcs.add(new ObjAbc(3, 125));
        objAbcs.add(new ObjAbc(4, 73));
        objAbcs.add(new ObjAbc(5, 12));
        objAbcs.add(new ObjAbc(1, 12));
        objAbcs.add(new ObjAbc(3, 1));
        return objAbcs;
    }

    public static void main(String[] args) {
        List<ObjAbc> list = populateList();
        List<ObjAbc> newList = new ArrayList<ObjAbc>();
        for (ObjAbc o : list) {
            if (!newList.isEmpty()) {
                boolean found = false;
                for (ObjAbc n : newList) {
                    if (o.getCode().intValue() == n.getCode().intValue()) {
                        n.setValue(n.getValue() + o.getValue());
                        found = true;
                    } 
                }
                if (!found) {
                    newList.add(o);
                }
            } 
            else {
                newList.add(o);
            }
        }

        for (ObjAbc n : newList) 
            System.out.println(n.toString());
    }
}
Claudiu
  • 1,469
  • 13
  • 21