Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
371 views
in Technique[技术] by (71.8m points)

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

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

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

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

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) {
    }
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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);
}

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)))));
}

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));
});

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...