2017-01-22 6 views
0

У меня есть arraylist объекта User, который содержит имя пользователя и пароль пользователя. Я создал метод updateUsername, чтобы попытаться изменить имя пользователя пользователя, и в нем я использовал indexOf, но он всегда возвращает -1 (он не может найти указанного пользователя в arraylist). МетодindexOf всегда возвращает -1

updateUsername:

public void updateUsername(User user, String username) { 
    ArrayList<User> users = getAllUsers(); 
    int i = users.indexOf(user); 
    user.setUsername(username); 
    users.set(i,user); 
    synToFile(users); 
} 

Этот метод вызывается в контроллере при нажатии кнопки:

public JFXListView<Label> lview2; 

@FXML 
void changeUsername(ActionEvent event) { 
    String username = newUserField.getText(); 
    UserDAO theDAO = new UserDAO(); 
    Label lbl = lview2.getSelectionModel().getSelectedItem(); 
    //the items in the listview are of object label 
    User u = theDAO.getUser(lbl.getText()); 
    theDAO.updateUsername(u,username); 
    ObservableList<Label> userList = theDAO.storeUsers(); 
    lview2.setItems(userList); 
} 

lview2 является ListView в отдельном контроллере - Я инстанцирован здесь отдельный контроллер:

changeUsernameController cu = (changeUsernameController)fxmlLoader.getController(); 
cu.lview2 = listView; 

Не думаю, что это необходимо, но я добавил методы getAllUsers(), synToFile() и getUser() здесь также:

public ArrayList<User> getAllUsers() { 
    Scanner sc; 
    String record = null; 
    String[] fields; 
    ArrayList<User> users = new ArrayList<User>(); 

    try { 
     sc = new Scanner(dataFile); 
     while (sc.hasNextLine()) { 
      record = sc.nextLine(); 
      fields = record.split(";"); 
      String username = fields[0]; 
      String password = fields[1]; 
      User u = new User(); 
      u.setPassword(password); 
      u.setUsername(username); 
      users.add(u); 
     } 
    } catch (FileNotFoundException e) { 
     System.out.println("No record found!"); 
     //e.printStackTrace(); 
    } 
    return users; 
} 

public void synToFile(ArrayList<User> userList) { 
    if (userList == null) { 
     return; 
    } 

    try { 
     FileWriter out = new FileWriter(dataFile); 
     for (User u: userList) { 
      out.append(u.toString() + "\n"); 
     } 
     out.close(); 
    }catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

public User getUser(String username) { 
    ArrayList<User> users = getAllUsers(); 
    User user = null; 
    for (User u: users) { 
     if (u.getUsername().equals(username)) { 
      user = u; 
      break; 
     } 
    } 
    return user; 
} 

Примечание: Я добавил отладки строки в методе updateUsername() - ArrayList как положено быть, и пользовательский объект также является правильным.

Класс пользователя:

package Server; 

import java.util.ArrayList; 


public class User { 

private String username; 
private String password; 
private ArrayList<Double> scoreList=new ArrayList<Double>(); 

public User() { 

} 


public String getUsername() { 
    return username; 
} 

public void setUsername(String username) { 
    this.username = username; 
} 

public String getPassword() { 
    return password; 
} 

public void setPassword(String password) { 
    this.password = password; 
} 

public String toString() { 
    return username + ";" + password; 
} 

public String usernameString() { 
    return username; 
} 
} 
+0

Показать класс пользователя, пожалуйста. Вы понимаете, как indexOf находит индекс? –

+1

Вы переопределили 'equals' в классе' User'? – Eran

+0

'indexOf' использует' equals (Object) ', вы можете показать нам код для этого? –

ответ

1

Вот рабочая версия класса User:

public class User { 

private String username; 
private String password; 
private ArrayList<Double> scoreList=new ArrayList<Double>(); 

public User() { 

} 


public String getUsername() { 
    return username; 
} 

public void setUsername(String username) { 
    this.username = username; 
} 

public String getPassword() { 
    return password; 
} 

public void setPassword(String password) { 
    this.password = password; 
} 

public String toString() { 
    return username + ";" + password; 
} 

public String usernameString() { 
    return username; 
} 
@Override 
    public boolean equals(Object obj) { 
     if (obj instanceof User){ 
      User tmp = (User)obj; 
      return tmp.getUsername().equals(getUsername()); 
     } 
     return false; 
    } 

} 

Я добавил только тест на имя пользователя в методе equals(), но вы можете также добавьте другие тесты, исходя из ваших требований.

-1

Вы должны Переопределение равных в классе пользователя для того, чтобы работать внутри IndexOf() метод (как указано в комментариях).

Примером может служить пример.

 public class User { 
     String username; 
     String password; 

     @Override 
     public boolean equals(Object obj) { 
      if (obj == null) { 
       return false; 
      } 
      if (!User.class.isAssignableFrom(obj.getClass())) { 
       return false; 
      } 

      final User other = (User) obj; 

      if ((this.username == null) ? (other.username != null) : !this.username.equals(other.username)) { 
       return false; 
      } 
      if (!this.password.equals(other.password)) { 
       return false; 
      } 
      return true; 
     } 
    } 

Как сказано в комментарии, IndexOf() не использует хэш-код, я знаю, что это не связано с вопросом, но это условность переопределить оба метода (равно и хэш-код), потому что вы собираетесь имеют проблемы с другими классами, такими как HashMap или HashSet, если вы не переопределите его.

+2

Примечание: 'indexOf' не использует' hashCode() ' –

+0

Спасибо за разъяснение. – LouizFC

2

Вы должны переопределить метод equals в классе User. Метод indexOf внутренне использует equals, чтобы узнать, равен ли каждый элемент массива входному параметру.

См. this ответ на вопрос о том, как переопределить equals в Java.

+0

Как мне переопределить его? – cosmo

0

IndexOf метод использует равен, чтобы проверить наличие или отсутствие объекта в списке ...

так что ваш USER класс должен правильно переопределить этот метод (hascode тоже)

это причина, по которой возвращаемый индекс равен -1, даже если пользовательский объект находится в списке.

здесь реализация

229  public int indexOf(Object o) { 
230   if (o == null) { 
231    for (int i = 0; i < size; i++) 
232     if (elementData[i]==null) 
233      return i; 
234   } else { 
235    for (int i = 0; i < size; i++) 
236     if (o.equals(elementData[i])) 
237      return i; 
238   } 
239   return -1; 
240  } 

refernce

+0

hashcode тоже ??? – CKing

+0

Hashcode полезен только при проверке равенства, не используется indexOf –

+0

@Tom Возьмите английский смысл * реализует * здесь пожалуйста :) – CKing

0

Если вы переопределяете equals, то два объекта равны, если они являются одним и тем же объектом. В этом случае вы предполагаете, что у них одинаковые username. Лучшим подходом является использование Map вместо списка и использование String в качестве ключа, хотя это делает класс User избыточным.

// Username to password 
public Map<String, String> getAllUsers() { 
    try (Stream stream = Files.lines(datafilePath)) { 
     return stream 
       .map(line -> line.split(";")) 
       .collect(Collectors.toMap(l -> l[0], l -> l[1])); 
} 

// to update the user 
Map<String, String> userToPasswordMap = getAllUsers(); 
String password = userToPasswordMap.remove(oldUsername); 
if (password == null) // error 
userToPasswordMap.put(newUsername, password); 
syncToFile(userToPasswordMap); 
Смежные вопросы