【问题标题】:Extracting db column data with filter and map in Java8在 Java8 中使用过滤器和映射提取 db 列数据
【发布时间】:2019-12-26 04:57:18
【问题描述】:

关于员工的表包含以下数据:员工 ID、员工姓名、经理 ID 和团队成员 ID。每个员工都会根据他们的团队规模有多个条目。假设团队中有 5 名其他成员的员工将有五行,其中员工和经理 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)。但是尝试使用员工 ID 拆分团队成员会返回第一个值,但次数正确。说:一个有 5 人的团队返回一个由 5 人组成的数组,其中包含第一个成员的 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 与我正在循环的那一行匹配的整行,而 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("");
}

【问题讨论】:

  • 你可以添加样本输入和相应的预期输出吗?很难理解你的描述。
  • @Eran 添加了一个示例 i/p -> o/p。现在这段代码只返回每个员工的第一个 teamId。包括经理 ID 是可选的。但是过滤器和地图组合格式是否正确?我对此有疑问。基于一列进行过滤并将不同的列放入数组中。
  • 输出的类型应该是什么?
  • @Eran 需要它为String[]
  • 如何在单个字符串数组中存储每个员工 ID 的团队 ID 列表?听起来您需要Map&lt;String,List&lt;String&gt;&gt;Map&lt;String,String[]&gt;

标签: java filter java-8 spring-data-jpa java-stream


【解决方案1】:

根据问题和cmets,您需要的是:

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 - 1] = list.parallelStream()
                                      .filter(obj -> obj.getId().equals(id))
                                      .map(ViewData::getManagerId)
                                      .findFirst()
                                      .orElse(null);

    System.out.println(teamIds.length + "\n");
}

【讨论】:

  • 在收到outofbounds 异常后执行了teamIds.length-1。但正确的值没有被过滤和映射到list.streams.filter.map .filter(obj -&gt; obj.getId().equals(id)).map(ViewData::getManagerId) 是我正在使用的,但这是将第一个匹配值一遍又一遍地存储到字符串[] 中。所以应用 distinct 返回一个大小为 1 的数组。所以alex 得到1101bran 得到1301。这就是为什么我认为这是 map 部分的逻辑问题。
  • @BharathYes 你确定你的输入包含多个不同的团队 ID 用于相同的 emp Id?如果是这样,它不应该返回单个值。如果删除 distinct() 会发生什么?
  • 是的。没有 distinct 它返回重复正确时间的第一个值。所以alex 得到1101 四次,bran 得到1301 五次。我试图把它分成两部分。过滤并创建一个List,然后映射该新List的值
  • @Bharath是的,这没有意义。也许您的输入列表(由getDataList() 返回)不包含您认为的内容。您是否尝试打印 List(假设 ViewData 覆盖 toString())?
  • 你是对的。对不起。我提取后的数据不正确
猜你喜欢
  • 1970-01-01
  • 2023-03-23
  • 1970-01-01
  • 1970-01-01
  • 2018-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多