Java 8, how can I implement a switch statement using streams?

前端 未结 4 1679
忘掉有多难
忘掉有多难 2020-11-28 15:08

I have a text file imgui.ini containing:

[Debug]
Pos=7,79
Size=507,392
Collapsed=0

[ImGui Demo]
Pos=320,5
Size=550,680
Collapsed=0
4条回答
  •  清歌不尽
    2020-11-28 15:56

    Focusing on the question "is there a way to simulate switch statement behavior", I think the answer is that you could, with a little effort. I asked myself that a couple of years ago, and did the following as an exercise (and then never used it again):

    private static  Predicate testAndConsume(Predicate pred, Consumer cons) {
        return t -> {
            boolean result = pred.test(t);
            if (result) cons.accept(t);
            return result;
        };
    }
    
    public static class SwitchConsumer {
        Predicate conditionalConsumer;
        private SwitchConsumer(Predicate pred) {
            conditionalConsumer = pred;
        }
    
        public static  SwitchConsumer inCase(Predicate pred, Consumer cons) {
            return new SwitchConsumer<>(testAndConsume(pred, cons));
        }
    
        public SwitchConsumer elseIf(Predicate pred, Consumer cons) {
            return new SwitchConsumer<>(conditionalConsumer.or(testAndConsume(pred,cons)));
        }
    
        public Consumer elseDefault(Consumer cons) {
            return testAndConsume(conditionalConsumer.negate(),cons)::test;   // ::test converts Predicate to Consumer
        }
    }
    

    testAndConsume composes a Predicate and a Consumer, creating a Predicate that returns the same value but calls the Consumer as a side-effect if the value is true. That becomes the basis for each "case" in the "switch". Each "case" is strung together by Predicate.or(), which provides the short-circuiting "else-if" nature of the switch. Finally, the composed Predicate is turned into a Consumer by adding ::test to the Predicate.

    Applying it to your code snippet, it looks like this:

        Stream.of("Pos=320,5", "Size=550,680", "Collapsed=0")
                .map(s -> s.split("="))
                .forEach(SwitchConsumer.
                        inCase(arr -> "Pos".equals(arr[0]), arr -> settings.pos = arr[1])
                        .elseIf(arr -> "Size".equals(arr[0]), arr -> settings.size = arr[1])
                        .elseIf(arr -> "Collapsed".equals(arr[0]), arr -> settings.collapsed = arr[1])
                        .elseDefault(arr -> {}));
    

    That's about as switch-ish as it can get without an actual switch in a Consumer body.

提交回复
热议问题