如何在Java8中强制立即评估流

时间:2016-02-01 22:19:34

标签: java lambda functional-programming java-8 java-stream

我想知道如何强制立即评估Java8中的每个map函数?我现在的情况是我需要进行多级转换(来自ObjectA - > ObjectB - > ObjectC - > ObjectD),并且对于某些对象,在此转换的每个级别上都可能存在失败(抛出异常) 。例如

case WM_INPUT: {
    UINT buffer_size = 48;
    LPBYTE buffer[48];
    GetRawInputData((HRAWINPUT)lparam, RID_INPUT, buffer, &buffer_size, sizeof(RAWINPUTHEADER));
    RAWINPUT* raw = (RAWINPUT*)buffer;
    if (raw->header.dwType != RIM_TYPEMOUSE) {
        break;
    }
    const RAWMOUSE& mouse = raw->data.mouse;
    if ((mouse.usFlags & MOUSE_MOVE_ABSOLUTE) == MOUSE_MOVE_ABSOLUTE) {
        static Vector3 last_pos = vector3(FLT_MAX, FLT_MAX, FLT_MAX);
        const bool virtual_desktop = (mouse.usFlags & MOUSE_VIRTUAL_DESKTOP) == MOUSE_VIRTUAL_DESKTOP;
        const int width = GetSystemMetrics(virtual_desktop ? SM_CXVIRTUALSCREEN : SM_CXSCREEN);
        const int height = GetSystemMetrics(virtual_desktop ? SM_CYVIRTUALSCREEN : SM_CYSCREEN);
        const Vector3 absolute_pos = vector3((mouse.lLastX / float(USHRT_MAX)) * width, (mouse.lLastY / float(USHRT_MAX)) * height, 0);
        if (last_pos != vector3(FLT_MAX, FLT_MAX, FLT_MAX)) {
            MouseMoveEvent(absolute_pos - last_pos);
        }
        last_pos = absolute_pos;
    }
    else {
        MouseMoveEvent(vector3((float)mouse.lLastX, (float)mouse.lLastY, 0));
    }
}
break;

我想测试我的单元测试中的每个转换,例如测试是否测试抛出异常,以及如果A转换为C时失败,当将A转换为B时出现异常,但是有懒惰评估,这变得无法测试,我能想到的唯一方法就是执行 // stream -> map -> collect sequence lists.stream() .map(aToB) .collect(Collectors.toList()) .stream() .map(bToC) .collect(Collectors.toList()) .stream() .map(cToD) .collect(Collectors.toList()) // Try api is from javaslangs Function<ObjectA, ObjectB> aToB = a -> Try.of(() -> .....) .onFailure(....) .get(); Function<ObjectB, ObjectC> bToC = b -> Try.of(() -> .....) .onFailure(....) .get(); Function<ObjectC, ObjectD> cToD = c -> Try.of(() -> .....) .onFailure(....) .get(); 次调用以迫使立即评估。我想知道是否有更好的方法来写这篇文章。

2 个答案:

答案 0 :(得分:4)

这里有一些简单的想法:

  • 测试单元素集合上的整个流操作链。验证在您期望的位置抛出异常。
  • 不要担心测试流框架;只需在测试中直接应用这些函数,而不是通过流。

一般来说,不要尝试在测试中处理延迟评估:测试函数,并信任流框架在实际代码中做正确的事情。

答案 1 :(得分:1)

您可以编写一个静态帮助器方法,该方法收集到一个集合中,然后返回该集合的流,并将流管道的各个步骤包装到该帮助器中。

您应该知道这会改变流的语义。

例如,如果在此问题中处理,则无限流源可能会失败,即使完整的流管道如果以短路操作终止也可能成功。类似地,并行性和并发性可能会发生变化。因此,您最终会测试与流管道本身不同的东西。

相反,最好只测试整个流管道,为可能的输入场景提供预期的输出,并可能分别在各种输入上测试映射函数。