在地图集中添加多个值的有效方法

时间:2019-04-12 16:10:49

标签: java dictionary collections java-8 java-stream

我正在尝试在redshift中创建多个用户(例如,创建用户“ abc”,密码为“ xyz”)。同样,当用户创建redshift时,我会将这些用户名及其密码存储在本地MySQL数据库中,但密码以加密格式存储。我目前的方法是:

Map<String, String> uNamePassForDB = new HashMap<>();
Map<String, String> uNamePassForRedshift = new HashMap<>();

listOfUsers.stream().forEach(u -> {
        String pass = //some random password generator;
        String encryptedPassword = //encrpts the password (i.e. pass)
        uNamePassForDB.put(u, encryptedPassword);
        uNamePassForRedshift.put(u, pass);
}

uNamePassForRedshift.entrySet().stream().forEach(e -> {
      // creating redshift connection and executing create user command
}

uNamePassForRedshift.entrySet().stream().forEach(e -> {
      // storing the encrypted password in my local MySQL Database
}

当前,在所有用户在redshift中成功创建后,我将存储“用户名|密码”。在Redshift上成功创建用户名|密码后,是否可行?这种方法对我有用。但是我该如何改进这种方法?如何简化这种方法?

2 个答案:

答案 0 :(得分:1)

首先,我建议您避免使用collection.stream().forEach()构造,因为Stream-API应该遵循non-interference原则。此外,您可以对任何forEach包括IterableList调用Set方法。

现在回到您的问题。更改Map值的问题已经讨论了很多次,我仍然想知道JDK没有为这个问题提供明确的解决方案。我个人认为,最好的方法之一是简单的迭代并替换值本身。即使在 +版本中,这也是一种合法的方式:

for (String user: listOfUsers) {
    String pass = "random password";
    String encryptedPassword = "encrypted password";
    uNamePassForDB.put(user, encryptedPassword);
    uNamePassForRedshift.put(user, pass);
}

由于您已经标记了,因此请尝试以声明的方式思考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
}

答案 1 :(得分:0)

类似这样的东西:

listOfUsers.stream().map(this::createUsernamePass).forEach(this::store);

其中createUsernamePass是创建包含您的用户名,密码和加密密码的数据对象的方法,而store(userNamePass)是执行数据库插入的方法。

(这是在iPad上编写的,未经测试,但是可以考虑这个想法)

您也可以并行执行此操作,也可以使其更快。