Во-первых, я предлагаю вам избегать конструкции collection.stream().forEach()
, поскольку Stream-API должен следовать принципу невмешательства . Более того, вы можете вызывать метод forEach
для любого Iterable
, включая List
или Set
.
Теперь вернемся к вашей проблеме. Проблема изменения значений Map
обсуждалась много раз, и я все еще удивляюсь, что JDK не дает четкого решения этой проблемы. Лично я считаю, что одним из лучших подходов является простая итерация и замена самих значений. Даже в версии java-8 + это законный путь:
for (String user: listOfUsers) {
String pass = "random password";
String encryptedPassword = "encrypted password";
uNamePassForDB.put(user, encryptedPassword);
uNamePassForRedshift.put(user, pass);
}
Поскольку вы пометили java-stream , попробуйте декларативно представить, что результат Stream
будет будет , а не делать (это отличие от процедурного for-loop
мышления). Единственный способ, который мне известен, это не нарушает принцип невмешательства и не вызывает побочных эффектов (генерация пароля все еще сомнительна):
// Each Stream should do ONE thing
final List<Credential> credentials = listOfUsers.stream()
.map(user -> new Credential(user, /* random password */ ))
.collect(Collectors.toList());
final Map<String, String> uNamePassForDB = credentials.stream()
.collect(Collectors.toMap(
Credential::getUser, // key
Credential::getEncryptedPassword)); // value
final Map<String, String> uNamePassForRedshift = credentials.stream()
.collect(Collectors.toMap(
Credential::getUser, // key
Credential::getPassword)); // value
Где создан неизменный класс Credential
для помощи:
public static class Credential {
private final String user;
private final String password;
private final String encryptedPassword;
public Credential(final String user, final String password) {
this.user = user;
this.password = password;
// I suggest this to avoid inconsistency
this.encryptedPassword = /* encrypt password */
}
// getters
}