Java 8,如何使用流实现 switch 语句? [英] Java 8, how can I implement a switch statement using streams?

查看:52
本文介绍了Java 8,如何使用流实现 switch 语句?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个文本文件 imgui.ini 包含:

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

对于每个元素",我总是有 PosSizeCollapsed,我需要阅读它们.

For each "element" I always have Pos, Size and Collapsed and I need to read them.

如果可能,我想使用 java 8 流.

I would like to use, if possible, java 8 streams.

是否可以模拟 switch 语句的行为?

Is it possible to simulate a switch statement behaviour?

    try (Stream<String> stream = Files.lines(Paths.get(context.io.iniFilename))) {

        ...
/*
    switch(string) {

        case "Pos":
            settings.pos = value;
            break;

        case "Size":
            settings.size = value;
            break;

        case "Collapsed":
            settings.collapsed = value;
            break;
    }
*/

    } catch (IOException e) {
    }
}

推荐答案

解析此类文件的最佳方法(不使用专用的 3rd 方库)是通过正则表达式 API 及其前端类 Scanner.不幸的是,目前缺少通过 Stream API 实现它的最佳操作.即,Matcher.results()Scanner.findAll(…) 还没有.因此,除非我们想等到 Java 9,否则我们必须为 Java 8 兼容解决方案创建类似的方法:

The best way to parse such a file (without using dedicated 3rd party libraries), is via the regex API, and its front-end class Scanner. Unfortunately, the best operations to implement it via Stream API, are currently missing. Namely, Matcher.results() and Scanner.findAll(…) are not there yet. So unless we want to wait until Java 9, we have to create similar methods for a Java 8 compatible solution:

public static Stream<MatchResult> findAll(Scanner s, Pattern pattern) {
    return StreamSupport.stream(new Spliterators.AbstractSpliterator<MatchResult>(
            1000, Spliterator.ORDERED|Spliterator.NONNULL) {
        public boolean tryAdvance(Consumer<? super MatchResult> action) {
            if(s.findWithinHorizon(pattern, 0)!=null) {
                action.accept(s.match());
                return true;
            }
            else return false;
        }
    }, false);
}
public static Stream<MatchResult> results(Matcher m) {
    return StreamSupport.stream(new Spliterators.AbstractSpliterator<MatchResult>(
            m.regionEnd()-m.regionStart(), Spliterator.ORDERED|Spliterator.NONNULL) {
        public boolean tryAdvance(Consumer<? super MatchResult> action) {
            if(m.find()) {
                action.accept(m.toMatchResult());
                return true;
            }
            else return false;
        }
    }, false);
}

一旦 Java 9 发布并变得司空见惯,使用具有相似语义的方法允许我们用标准 API 方法替换它们的用法.

Using methods with a similar semantic allows us to replace their usage with the standard API methods, once Java 9 is released and becomes commonplace.

使用这两个操作,您可以使用

Using these two operations, you can parse your file using

Pattern groupPattern=Pattern.compile("\[(.*?)\]([^\[]*)");
Pattern attrPattern=Pattern.compile("(.*?)=(.*)\v");
Map<String, Map<String, String>> m;
try(Scanner s=new Scanner(Paths.get(context.io.iniFilename))) {
    m = findAll(s, groupPattern).collect(Collectors.toMap(
        gm -> gm.group(1),
        gm -> results(attrPattern.matcher(gm.group(2)))
            .collect(Collectors.toMap(am->am.group(1), am->am.group(2)))));
}

结果映射 m 包含所有信息,从组名映射到另一个包含键/值对的映射,即您可以使用打印等效的 .ini 文件:

the resulting map m holds all information, mapping from the group names to another map holding the key/value pairs, i.e. you can print an equivalent .ini file using:

m.forEach((group,attr)-> {
    System.out.println("["+group+"]");
    attr.forEach((key,value)->System.out.println(key+"="+value));
});

这篇关于Java 8,如何使用流实现 switch 语句?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆