java - 如何在匿名函数中使用计数器?

标签 java lambda counter final

使用 Java 8,我想要两个组合为集合:一个集合是 java.util.List;另一个是 com.fasterxml.jackson.databind.node.ArrayNode

这是处理该问题的非 Java 8 方法:

private void mergeMemberAndRelationshipData(final List<JsonNode> members, final ArrayNode relationships) {

    assert members != null : "members cannot be null";
    assert relationships != null : "relationships cannot be null";

    for (int i = 0; i < members.size(); i++) {

        final ObjectNode relationship = (ObjectNode) relationships.get(i);
        final JsonNode member = members.get(i);

        if (member != null && !member.hasNonNull(ExceptionMapper.errorCodeStr)) {
            relationship.put(FIRST_NAME, this.jsonHelpers.safeGetString(member, FIRST_NAME));
            relationship.put(LAST_NAME, this.jsonHelpers.safeGetString(member, LAST_NAME));
            relationship.put(EMAIL, this.jsonHelpers.safeGetString(member, EMAIL));
            relationship.put(MEMBER_SINCE, this.jsonHelpers.safeGetString(member, MEMBER_SINCE));
        } else {
            LOGGER.error("No corresponding Member, {}, found for Relationship: {}", member, relationship);
        }
    }
}

我想直播。我喜欢溪流。好吧,那么我们来试试吧:

private void mergeMemberAndRelationshipData(final List<JsonNode> members, final ArrayNode relationships) {

    assert members != null : "members cannot be null";
    assert relationships != null : "relationships cannot be null";

    int i = 0;

    members.stream().forEach(member -> {
        final ObjectNode relationship = (ObjectNode) relationships.get(i++);

        if (member != null) {
            relationship.put(FIRST_NAME, this.jsonHelpers.safeGetString(member, FIRST_NAME));
            relationship.put(LAST_NAME, this.jsonHelpers.safeGetString(member, LAST_NAME));
            relationship.put(EMAIL, this.jsonHelpers.safeGetString(member, EMAIL));
            relationship.put(MEMBER_SINCE, this.jsonHelpers.safeGetString(member, MEMBER_SINCE));
        } else {
            LOGGER.warn("No corresponding member found for relationship: {}", relationship);
        }
    });
}

但是不,这是行不通的:我在封闭范围内定义的局部变量必须是最终的或实际上是最终的。是的,这是有道理的。有点。

好吧,所以我想流式传输一个集合 A,并且对于 A 中的每个对象,对集合 B 中的相应对象执行一些操作。我需要知道索引才能做到这一点。

如何在匿名函数内部使用在匿名函数范围之外声明的计数器?

我可以通过创造性的方式解决这个问题:

private void mergeMemberAndRelationshipData(final List<JsonNode> members, final ArrayNode relationships) {

    assert members != null : "members cannot be null";
    assert relationships != null : "relationships cannot be null";

    int[] i = new int[1];
    i[0] = 0;

    members.stream().forEach(member -> {
        final ObjectNode relationship = (ObjectNode) relationships.get(i[0]);
        i[0] = i[0]++;

        if (member != null) {
            relationship.put(FIRST_NAME, this.jsonHelpers.safeGetString(member, FIRST_NAME));
            relationship.put(LAST_NAME, this.jsonHelpers.safeGetString(member, LAST_NAME));
            relationship.put(EMAIL, this.jsonHelpers.safeGetString(member, EMAIL));
            relationship.put(MEMBER_SINCE, this.jsonHelpers.safeGetString(member, MEMBER_SINCE));
        } else {
            LOGGER.warn("No correspodning member foudn for relationship: {}", relationship);
        }
    });
}

或者我可以这样使用 AtomicInteger:

AtomicInteger i = new AtomicInteger(0);
...
final ObjectNode relationship = (ObjectNode) relationships.get(i.getAndIncrement());

但这是对 AtomicInteger 的误用;这意味着线程之间共享值。不完全是这里发生的事情,而且它太重量级了,不适合使用(在我看来,请随意不同意我的观点)。

因此,这是很常见的事情(链接两个有序列表并对其元素进行操作)。在 Java 8 之前,这非常简单(技术上仍然如此,但我确信你们这些学究们明白我的意思)。有没有一种 Java-8 的方法可以使用流来完成这个任务?

对于我工作的环境,我们使用微服务架构方法。这意味着我们有一堆服务负责一组离散的、封装的职责(例如,MemberService 处理成员 CRUD,CompanyService 处理公司 CRUD)。最重要的是,我们有一个编排/身份验证/授权服务,可以发出这些不同的调用,然后将它们缝合在一起。因此,在我粘贴的方法中,这是编排层,我在其中获取两个数据集,现在我想将它们合并在一起。这就是为什么我没有 LinkedList 或其他类似的解决方案。

最佳答案

您想要查找压缩。 Java 最初内置了一个 zip 实用程序,但后来被删除了。这是过去的 stackoverflow 响应,用于使用示例实现来进行流压缩:Zipping streams using JDK8 with lambda (java.util.stream.Streams.zip) .

除此之外,为了避免在外部保留索引,您可以使用 IntStream:

final List<String> a = Arrays.asList("a", "b", "c");
final List<String> b = Arrays.asList("1", "2", "3");
IntStream.range(0, Math.min(a.size(), b.size()))
   .mapToObj(i -> a.get(i) + "-" + b.get(i))
   .forEach(System.out::println);

关于java - 如何在匿名函数中使用计数器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38254397/

相关文章:

c++ - 了解 C++ lambda 捕获规范中的 [&]

c++ - 为什么 c++11 中的 lambda 函数没有 f​​unction<> 类型?

javascript - 倒计时功能实际上并没有倒计时

Python 循环收集数据

java - 当字符串不可变时,为什么 System.out.println(s.concat ("some string"));返回改变后的值

java - Spring Hibernate 生成动态查询

c++ - 如何从 C++14 中的广义 lambda 捕获返回包含 std::unique_ptr 的 std::function ?

python - 计算数据框中每一行和特定列在列表中的出现次数

java - 将 Java 字符串拆分为具有特殊字符和复杂情况的空格

迄今为止的 Java 字符串