英文:
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<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) {
}
});
}
}
答案1
得分: 2
在这里:
for (User user1 : mUsers){ // 此处有错误
if (!user.getId().equals(user1.getId())){
mUsers.add(user);
}
}
在使用迭代器进行迭代时向集合中添加元素是不被允许的。请注意,你在编译后使用的“增强for循环”实际上被表示为[`Iterator`][1]。
为了克服这个限制,你可以使用[`ListIterator`][2],它是(强调是我的):
> 用于列表的迭代器,允许程序员**在列表中遍历**(以任何方向),**在迭代期间修改列表**,并获取迭代器的当前位置。
ListIterator<User> 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<User> listIteratorUser = mUsers.listIterator();
while(listIteratorUser.hasNext()){
User user1 = listIteratorUser.next();
if (!user.getId().equals(user1.getId())){
listIteratorUser.add(user);
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论