关于员工的表具有以下数据:员工ID、员工姓名、经理ID和团队成员ID。每个员工将根据其团队规模有多个条目。假设团队中有5个其他成员的员工将有5行,其中员工ID和经理ID与每个团队成员的ID重复。
样品表:
employeeId | employeeName | managerId | teamEmployeeId |
-------------------------------------------------------
1000 | Alex | 4000 | 1101 |
1200 | Bran | 4100 | 1301 |
1200 | Bran | 4100 | 1302 |
1000 | Alex | 4000 | 1102 |
1200 | Bran | 4100 | 1303 |
1000 | Alex | 4000 | 1103 |
1200 | Bran | 4100 | 1304 |
1200 | Bran | 4100 | 1305 |
1000 | Alex | 4000 | 1104 |
字符串
我们的目标是将每个员工的团队ID(以及经理ID)拆分到一个单独的数组中,以便稍后使用。
预期结果:
allIds:
1000
1200
teamIds for "Alex" :
1101
1102
1103
1104
4000
teamIds for "Bran" :
1301
1302
1303
1304
1305
4100
型
获取唯一员工ID的第一部分正在工作(基于此answer)。但是尝试使用employee id拆分团队成员时,返回的是第一个值,但次数是正确的。假设:一个有5个成员的团队返回一个包含5个成员的数组,其中第一个成员的id为所有成员的id。未添加经理的ID。
我使用的代码:
List<ViewData> list = getDataList();
String[] allIds = list.parallelStream()
.map(ViewData::getId).distinct().toArray(String[]::new);
System.out.println(allIds.length + "\n");
for (String id : allIds) {
String[] teamIds = list.parallelStream()
.filter(row -> row.getId().equals(id))
.map(ViewData::getTeamId).distinct()
.toArray(String[]::new);
teamIds = Arrays.copyOf(teamIds, teamIds.length+1 );
teamIds[teamIds.length] = list.parallelStream()
.filter(obj -> obj.getId().equals(id))
.map(ViewData::getManagerId).toString();
System.out.println(teamIds.length + "\n");
}
型
我知道这是个逻辑错误。我引用的所有filter()文档都显示语法是正确的。我的理解是,filter()返回id与我正在循环的id匹配的整行,map()从该行中取出团队成员的id,最后所有内容都以字符串数组的形式返回。
我哪里做错了?写代码还是理解这些函数是如何工作的?
编辑:
如果这样的表导致重复/重复行(特别是它应该出现的确切次数):
没有主键的视图(即,没有保证唯一的列)需要通过组合两个列而导出的复合主键,这两个列随后将是唯一的。
- 为复合键组合创建单独的
@Embeddable
类 - 将其添加到主模型类:
@EmbeddedId private UniqueId uniqueId;
个 - 按照答案中的现有逻辑继续:
for (String id : allIds) {
String[] teamIds = list.stream()
.filter(row -> row.getUniqueId().getId().equals(id))
.map(obj -> obj.getUniqueId().getTeamEmployeeId())
.toArray(String[]::new);
teamIds = Arrays.copyOf(teamIds, teamIds.length + 1);
teamIds[teamIds.length - 1] = list.stream()
.filter(obj -> obj.getUniqueId().getId().equals(id))
.map(ViewData::getManagerId).findFirst().orElse("");
String empName = list.stream()
.filter(obj -> obj.getUniqueId().getId().equals(id))
.map(ViewData::getName).findFirst().orElse("");
}
型
更新:
这是一个非常复杂的解决方案,因为对数据结构的理解有限。使用Set的自动重复数据消除功能的更简单(略微冗余)解决方案:
Map<Integer, Set<Integer>> res = new HashMap<>();
employeeDetails.forEach(o-> {
Integer empId = o.empId;
if(!res.containsKey(empId)) res.put(empId, new HashSet<>());
res.get(empId).addAll(Set.of(o.teamMemberId, o.managerId));
});
return res;
型
即使这也不是一个非常理想的解决方案。它对res
Map及其值进行了大量访问和修改。但与前面的方法不同,这种方法只遍历记录列表一次。两种解决方案的一些基本基准测试表明,新方法对于1000大小的记录快3-4倍,对于100秒内的大小快10倍。
但是超过5000个会使两者更加接近,因为它们都被为存储结果和访问结果而创建的对象数量所困扰。
1条答案
按热度按时间trnvg8h31#
根据问题和评论,您需要的是:
字符串