[英]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
循环可以替换为现有流中第二次调用map
和toMap
收集器:
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.