java.util.ConcurrentModificationException 在 for 循环中的错误

huangapple go评论76阅读模式
英文:

java.util.ConcurrentModificationException Error in for loop

问题

private UserAdapter userAdapter;
private List<User> mUsers;
FirebaseUser fuser;
DatabaseReference reference;
private List<String> usersList;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_chats, container, false);

    recyclerView = view.findViewById(R.id.recycle_view);
    recyclerView.setHasFixedSize(true);
    recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));

    fuser = FirebaseAuth.getInstance().getCurrentUser();

    usersList = new ArrayList<>();

    reference = FirebaseDatabase.getInstance().getReference("Chat");
    reference.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            usersList.clear();

            for (DataSnapshot snapshot : dataSnapshot.getChildren()){
                Chat chat = snapshot.getValue(Chat.class);

                assert chat != null;
                if (chat.getSender().equals(fuser.getUid())){
                    usersList.add(chat.getReceiver());
                }
                if (chat.getReceiver().equals(fuser.getUid())){
                    usersList.add(chat.getSender());
                }
            }
            readChats();

        }

        @Override
        public void onCancelled(@NonNull DatabaseError error) {

        }
    });

    return view;
}

public void readChats(){
    mUsers = new ArrayList<>();
    reference = FirebaseDatabase.getInstance().getReference("Users");
    reference.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            mUsers.clear();
            for (DataSnapshot snapshot : dataSnapshot.getChildren()){
                User user = snapshot.getValue(User.class);

                // display user from chats
                for (String id : usersList){

                    if (user.getId().equals(id)){
                        if (mUsers.size() != 0){
                            for (User user1 : mUsers){   // error here
                                if (!user.getId().equals(user1.getId())){
                                    mUsers.add(user);
                                }
                            }
                        }else {
                            mUsers.add(user);
                        }
                    }
                }
            }

            userAdapter = new UserAdapter(getContext(), mUsers);
            recyclerView.setAdapter(userAdapter);
        }

        @Override
        public void onCancelled(@NonNull DatabaseError error) {

        }
    });
}
英文:

when i build my project no error appears but when the application start it crashed and give me that error in line 97 in the for loop [ for (User user1 : mUsers) ]
the error is: FATAL EXCEPTION: main Process: com.example.chatapp, PID: 9908
java.util.ConcurrentModificationException

i didn't understand that error and why this error appears.

here is my code:

private UserAdapter userAdapter;
private List&lt;User&gt; mUsers;
FirebaseUser fuser;
DatabaseReference reference;
private List&lt;String&gt;usersList;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_chats, container, false);
recyclerView = view.findViewById(R.id.recycle_view);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
fuser = FirebaseAuth.getInstance().getCurrentUser();
usersList = new ArrayList&lt;&gt;();
reference = FirebaseDatabase.getInstance().getReference(&quot;Chat&quot;);
reference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
usersList.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()){
Chat chat = snapshot.getValue(Chat.class);
assert chat != null;
if (chat.getSender().equals(fuser.getUid())){
usersList.add(chat.getReceiver());
}
if (chat.getReceiver().equals(fuser.getUid())){
usersList.add(chat.getSender());
}
}
readChats();
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
}
});
return view;
}
public void readChats(){
mUsers = new ArrayList&lt;&gt;();
reference = FirebaseDatabase.getInstance().getReference(&quot;Users&quot;);
reference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
mUsers.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()){
User user = snapshot.getValue(User.class);
// display user from chats
for (String id : usersList){
if (user.getId().equals(id)){
if (mUsers.size() != 0){
for (User user1 : mUsers){   // error here
if (!user.getId().equals(user1.getId())){
mUsers.add(user);
}
}
}else {
mUsers.add(user);
}
}
}
}
userAdapter = new UserAdapter(getContext(), mUsers);
recyclerView.setAdapter(userAdapter);
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
}
});
}

}

答案1

得分: 2

在这里

    for (User user1 : mUsers){   // 此处有错误
            if (!user.getId().equals(user1.getId())){
                mUsers.add(user);
            }
    }

在使用迭代器进行迭代时向集合中添加元素是不被允许的请注意你在编译后使用的增强for循环实际上被表示为[`Iterator`][1]

为了克服这个限制你可以使用[`ListIterator`][2]它是强调是我的):

&gt; 用于列表的迭代器允许程序员**在列表中遍历**以任何方向),**在迭代期间修改列表**并获取迭代器的当前位置

    ListIterator&lt;User&gt; listIteratorUser = mUsers.listIterator();
    while(listIteratorUser.hasNext()){   
          User user1 = listIteratorUser.next();
          if (!user.getId().equals(user1.getId())){
              listIteratorUser.add(user);
          }
      }


  [1]: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Iterator.html
  [2]: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/ListIterator.html
英文:

Here :

for (User user1 : mUsers){   // error here
if (!user.getId().equals(user1.getId())){
mUsers.add(user);
}
}

You add an element in the collection while you iterate on that with an Iterator. That is not allowed.
Note that the enhanced for loop that you use for (User user1 : mUsers) after compilation is expressed as an Iterator.

To overcome that limitation you could use a ListIterator that is (emphasis is mine) :

> An iterator for lists that allows the programmer to traverse the list
> in either direction, modify the list during iteration, and obtain the
> iterator's current position in the list.

ListIterator&lt;User&gt; listIteratorUser = mUsers.listIterator();
while(listIteratorUser.hasNext()){   
User user1 = listIteratorUser.next();
if (!user.getId().equals(user1.getId())){
listIteratorUser.add(user);
}
}

huangapple
  • 本文由 发表于 2020年8月16日 18:37:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/63435839.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定