简体   繁体   English

如何将字符串列表转换为对象列表?

[英]How to convert a list of strings into a list of objects?

I have a list of roles in a database.我有一个数据库中的角色列表。 They are of the form它们的形式

application.Role1.read
application.Role1.write
application.Role2.read
application.Role3.read

So each role has an entry based on read/write permission.所以每个角色都有一个基于读/写权限的条目。 I want to convert the roles into a POJO which I can then send as JSON to a UI.我想将角色转换为 POJO,然后我可以将其作为 JSON 发送到 UI。 Each POJO would have the role name, and a boolean for read or write permission.每个 POJO 都有角色名称,以及一个用于读取或写入权限的布尔值。

Here is the RolePermission class:这是 RolePermission 类:

import com.fasterxml.jackson.annotation.JsonInclude;

@JsonInclude(JsonInclude.Include.NON_NULL)
public class RolePermission {
    private String roleName;
    private boolean readAllowed;
    private boolean writeAllowed;

    public String getRoleName() {
        return roleName;
    }

    public RolePermission setRoleName(String roleName) {
        this.roleName = roleName;
        return this;
    }

    public boolean isReadAllowed() {
        return readAllowed;
    }

    public RolePermission setReadAllowed(boolean readAllowed) {
        this.readAllowed = readAllowed;
        return this;
    }

    public boolean isWriteAllowed() {
        return writeAllowed;
    }

    public RolePermission setWriteAllowed(boolean writeAllowed) {
        this.writeAllowed = writeAllowed;
        return this;
    }
}

I am doing the transformation like so:我正在做这样的转换:

public static final String ROLE_PREFIX = "application.";
public static final String ROLE_READ_PERMISSION = "read";
public static final String ROLE_WRITE_PERMISSION = "write";

@Override
public List<RolePermission> getRoles(Backend backend) {
    List<String> allRoles = backend.getRoles()
            .stream()
            .map(s -> s.replace(ROLE_PREFIX, ""))
            .sorted()
            .collect(Collectors.toList());
    Map<String, RolePermission> roleMap = new HashMap<>();
    for (String role : allRoles) {
        String[] tokens = role.split(".");
        String roleName = tokens[0];
        String permission = tokens[1];
        if (!roleMap.containsKey(roleName))
            roleMap.put(roleName, new RolePermission().setRoleName(roleName));
        RolePermission permission = roleMap.get(roleName);
        if (ROLE_READ_PERMISSION.equals(permission))
            permission.setReadAllowed(true);
        if (ROLE_WRITE_PERMISSION.equals(permission))
            permission.setWriteAllowed(true);
    }
    return new LinkedList<>(roleMap.values());
}

Is there a way to do the foreach loop above using Java 8 streams?有没有办法使用 Java 8 流执行上面的 foreach 循环?

This is a mock Backend instance that just returns a list of roles:这是一个只返回角色列表的模拟后端实例:

public class Backend {
    public List<String> getRoles() {
        return Arrays.asList(
            "application.Role1.read",
            "application.Role1.write",
            "application.Role2.read",
            "application.Role3.read"
        );
    }
}

You can use groupingBy to join the different permissions for the same roleName together.您可以使用groupingBy将同一个 roleName 的不同权限连接在一起。

public static final String ROLE_PREFIX = "application.";
public static final String ROLE_READ_PERMISSION = "read";
public static final String ROLE_WRITE_PERMISSION = "write";

@Override
public List<RolePermission> getRoles(Backend backend) {
    Map<String, List<String[]>> allRoles = backend.getRoles()
            .stream()
            .map(s -> s.replace(ROLE_PREFIX, "")) // something like "Role1.read"
            .map(s -> s.split("\\.")) // something like ["Role1", "read"]
            .collect(Collectors.groupingBy(split -> split[0]));
    return allRoles.values()
                   .stream()
                   .map(this::buildPermission)
                   .collect(Collectors.toList());
}

private RolePermission buildPermission(List<String[]> roleEntries) {
    RolePermission permission = new RolePermission().setRoleName(roleEntries.get(0)[0]);
    roleEntries.stream()
               .forEach(entry -> {
                   if (ROLE_READ_PERMISSION.equals(entry[1]))
                       permission.setReadAllowed(true);
                   if (ROLE_WRITE_PERMISSION.equals(entry[1]))
                       permission.setWriteAllowed(true);
               });
    return permission;
}

I also think that your String.split was using an incorrect regex in the original post, because .我还认为您的String.split在原始帖子中使用了不正确的正则表达式,因为. is a special regex character .是一个特殊的正​​则表达式字符 I've tested this and it works correctly.我已经测试过这个并且它工作正常。

Output:输出:

[RolePermission(roleName=Role3, readAllowed=true, writeAllowed=false), 
 RolePermission(roleName=Role2, readAllowed=true, writeAllowed=false),
 RolePermission(roleName=Role1, readAllowed=true, writeAllowed=true)]

Your for loop can be replaced with second call of map in your existing stream and toMap collector:您的for循环可以替换为现有流中第二次调用maptoMap收集器:

public List<RolePermission> getRoles(Backend backend)
{
    Map<String, RolePermission> allRoles = backend.getRoles()
            .stream()
            .map(s -> s.replace(ROLE_PREFIX, ""))
            .sorted()
            .map(this::mapStringToRolePermission)
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, RolePermission::merge));
    return new ArrayList<>(allRoles.values());
}

where mapStringToRolePermission :其中mapStringToRolePermission

private static Map.Entry<String, RolePermission> mapStringToRolePermission(String role)
{
    String roleName = role.substring(0, role.indexOf('.'));
    RolePermission rolePermission = new RolePermission();
    rolePermission.setRoleName(roleName);
    rolePermission.setReadAllowed(role.endsWith(ROLE_READ_PERMISSION));
    rolePermission.setWriteAllowed(role.endsWith(ROLE_WRITE_PERMISSION));
    return new AbstractMap.SimpleEntry<>(roleName, rolePermission);
}

and an additional method merge for RolePermission :RolePermission的附加方法merge

public RolePermission merge(RolePermission another)
{
    if (another.isReadAllowed())
        setReadAllowed(true);
    if (another.isWriteAllowed())
        setWriteAllowed(true);
    return this;
}

The Java stream has a map function so you could use that to map String to RolePermission (or whatever object you want) and then collect the results to a list. Java 流有一个 map 函数,因此您可以使用它来将 String 映射到 RolePermission(或您想要的任何对象),然后将结果收集到一个列表中。 Would something like this work for you?这样的事情对你有用吗? It looks like you more or less already have the String to RolePermission conversion done看起来您或多或少已经完成了 String 到 RolePermission 的转换

final List<RolePermission> roles = getRoles().stream().map(roleString -> { <your conversion code> }).collect(Collectors.toList());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM