1

I have a button "Cart" that do select * query and add items(articles) in ArrayList, since i want to avoid to add articles in list every time button is clicked i tried this:

for(Article a : articleList){
     String checkId = "select * from article";
     PreparedStatement ps = conn.prepareStatement(checkId);
     ResultSet rs = ps.executeQuery(checkId);
     rs.next();
     if(a.getId()==rs.getInt("id")){
      //Here i'm returning list, just like it is in DataBase.
    } else{
        //Here i want to add articles in the list
    }
 }

I assume that i'm getting that exception because i'm adding articles in ArrayList while traversing through the same list. How can i fix this?

nemke nemke
  • 191
  • 1
  • 1
  • 9
  • 1
    Add them to another `List`. – Unmitigated Jul 15 '20 at 19:19
  • You are only looking at the first row returned from you query. Maybe you should change your SQL to something like 'select count(*) from article where id = ?', then ps.setInteger(a.getId()) – jnorman Jul 15 '20 at 19:35

2 Answers2

0

As already pointed out, your assumption is right. You are getting the ConcurrentModificationException for trying to modify the list while iterating over it. You just need to collect the query result beforehand and then iterate over the articleList.

I'd suggest you implement these collections using Set rather than List. It would be much more efficient, but you would need to override the Article equals() and hashcode() methods to guarantee the correct comparison.

Otherwise, you can use Java 8 Stream.concat to concatenate both Lists and then deduplicate the result inserting them in a LinkedHashMap (for efficient access) using the Article id as key.

String checkId = "select * from article";
PreparedStatement ps = conn.prepareStatement(checkId);
ResultSet rs = ps.executeQuery();
List<Article> dbArticles = new ArrayList<>();
while(rs.next()) {
  dbArticles.add(
     Article.of(
        rs.getInt("id") 
        /* rs.get...retrieve all other attributes */
     )
  );
}

Collection<Article> result = Stream.concat(dbArticles.stream(), articleList.stream())
    .collect(Collectors.toMap(Article::getId, 
             Function.identity(), 
             (l, r) -> l, 
             LinkedHashMap::new)
    ).values();
dbaltor
  • 2,737
  • 3
  • 24
  • 36
  • 1
    Thanks for answering but i need to learn streams and lambda expressions so i can read this :D – nemke nemke Jul 16 '20 at 18:17
  • 1
    Don't let the different syntax and some new concepts to put you off. For example, the lambda `(l, r) -> l` represents a function that gets 2 arguments (of any types) and will return the left one, [here](https://docs.oracle.com/javase/8/docs/api/java/util/function/BiFunction.html) is the definition using generics. It is used in your case to decide which (key, value) pair will be kept in the collection when they've got the same key. I'd say the most important thing is the fact you spotted on the issue of mutating the collection when iterating over it. Well done! – dbaltor Jul 16 '20 at 20:29
  • Okay i think i got an idea, and don't worry i'm not gonna get put off, this is exiting to me, mine plan was to learn streams, lambda expressions and design patterns right after i finish this book store, so thanks again. I solved problem without iterating over Arraylist. – nemke nemke Jul 16 '20 at 20:56
0

you question is the flow code

public static void main(String[] args) {
    List<Integer> integerList = new ArrayList<>();
    integerList.add(1);
    integerList.add(2);
    for (Integer integer : integerList) {
        integerList.add(3);
    }
}

the error is that

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:907)
    at java.util.ArrayList$Itr.next(ArrayList.java:857)
    at com.test.TestList.main(TestList.java:28)

we could use ListIterator to add the value.The code is this

package com.test;

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

/**
 *
 *
 *
 *
 * @author shikai.liu
 * @version 1.0
 * @since JDK1.7
 */
public class TestList {
    public static void main(String[] args) {
        List<Integer> integerList = new ArrayList<>();
        integerList.add(1);
        integerList.add(2);
        // for (Integer integer : integerList) {
        // integerList.add(3);
        // }
        ListIterator<Integer> integerIterator = integerList.listIterator();
        while (integerIterator.hasNext()) {
            Integer integer = integerIterator.next();
            if (integer == 1)
                integerIterator.add(5);
        }

    }
}

so your code is like that

ListIterator<Article> integerIterator = articleList.listIterator();
        while (integerIterator.hasNext()) {
            Article a = integerIterator.next();
            String checkId = "select * from article";
            PreparedStatement ps = conn.prepareStatement(checkId);
            ResultSet rs = ps.executeQuery(checkId);
            rs.next();
            if(a.getId()==rs.getInt("id")){
                //Here i'm returning list, just like it is in DataBase.
            } else{
                //integerIterator.add()
                //Here i want to add articles in the list
            }
        }
sk l
  • 81
  • 1
  • 5