Java8,如何使用流实现switch语句?
我有一个文本文件Java8,如何使用流实现switch语句?,java,java-8,switch-statement,java-stream,Java,Java 8,Switch Statement,Java Stream,我有一个文本文件imgui.ini包含: [Debug] Pos=7,79 Size=507,392 Collapsed=0 [ImGui Demo] Pos=320,5 Size=550,680 Collapsed=0 对于每个“元素”,我总是有Pos,大小和折叠,我需要阅读它们 如果可能的话,我想使用Java8流 是否可以模拟switch语句行为 try (Stream<String> stream = Files.lines(Paths.get(context.io
imgui.ini
包含:
[Debug]
Pos=7,79
Size=507,392
Collapsed=0
[ImGui Demo]
Pos=320,5
Size=550,680
Collapsed=0
对于每个“元素”,我总是有Pos
,大小
和折叠
,我需要阅读它们
如果可能的话,我想使用Java8流
是否可以模拟switch语句行为
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) {
}
}
try(Stream=Files.line(path.get(context.io.ini文件名))){
...
/*
开关(字符串){
案例“Pos”:
settings.pos=值;
打破
案例“大小”:
settings.size=值;
打破
“崩溃”案例:
settings.collapsed=值;
打破
}
*/
}捕获(IOE异常){
}
}
尝试:
try {
Path file = Paths.get("G:\\tmp", "img.ini");
Stream<String> lines = Files.lines(file);
lines.filter(line->{
if("pos".equalsIgnoreCase(line.split("=")[0])){
//process pos line here
System.out.println("pos"+line);
return false;
}
return true;
}).filter(line->{
System.out.println("2"+line);
if("Collapsed".equalsIgnoreCase(line.split("=")[0])){
//process Collapsed line here
System.out.println("Collapsed"+line);
return false;
}
return true;
}).filter(line->{
System.out.println("3"+line);
if("Size".equalsIgnoreCase(line.split("=")[0])){
//process Size line here
System.out.println("Size"+line);
return false;
}
return true;
}).forEach(line->{
//settings = new Settings();
});;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
试试看{
路径文件=Path.get(“G:\\tmp”、“img.ini”);
流行=文件。行(文件);
行。过滤器(行->{
if(“pos”.equalsIgnoreCase(第行拆分(“=”[0])){
//在此处理pos行
系统输出打印项次(“pos”+行);
返回false;
}
返回true;
}).filter(行->{
系统输出打印项次(“2”+行);
if(“Collapsed”.equalsIgnoreCase(line.split(“=”[0])){
//这里是一条折叠线
System.out.println(“折叠”+行);
返回false;
}
返回true;
}).filter(行->{
系统输出打印项次(“3”+行);
if(“Size”.equalsIgnoreCase(第.split行(“=”[0])){
//这里是工艺尺寸线
系统输出打印项次(“尺寸”+行);
返回false;
}
返回true;
}).forEach(行->{
//设置=新设置();
});;
}捕获(IOE异常){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
解析此类文件(无需使用专用的第三方库)的最佳方法是通过regex API及其前端类Scanner
。不幸的是,目前缺少通过流API实现它的最佳操作。也就是说,现在还没有。因此,除非我们想等到Java 9,否则我们必须为Java 8兼容的解决方案创建类似的方法:
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);
}
读取配置文件的另一种方法:
public class Main {
public static void main(String[] args) throws IOException {
Path path = Paths.get("D:\\Development\\workspace\\Application\\src\\main\\resources\\init.txt");
String content = new String(Files.readAllBytes(path));
Map<String, Config> configMap = Stream.of(content.split("\\n\\r"))
.map(config -> Arrays.asList(config.split("\\r")))
.collect(HashMap<String, Config>::new, (map, list) -> {
String header = list.get(0);
String pos = list.get(1);
String size = list.get(2);
String collapsed = list.get(3);
map.put(header, new Config(pos.substring(pos.indexOf("=") + 1), size.substring(size.indexOf("=") + 1), collapsed.substring(collapsed.indexOf("=") + 1)));
}, (m, u) -> {});
System.out.println(configMap);
}
}
class Config {
public String pos;
public String size;
public String collapsed;
public Config(String pos, String size, String collapsed) {
this.pos = pos;
this.size = size;
this.collapsed = collapsed;
}
@Override
public String toString() {
return "Config{" + "pos='" + pos + '\'' + ", size='" + size + '\'' +
", collapsed='" + collapsed + '\'' + '}';
}
}
专注于“有没有一种方法可以模拟switch语句行为”这个问题,我认为答案是,您可以,只需一点努力。几年前我问自己,并做了以下练习(然后再也没有使用过):
这是在消费者
体内没有实际开关的情况下所能达到的最大开关。你的问题不清楚-你想打开什么?听起来您可能想首先编写一个方法来读取这些行并返回一个Map
(其中ConfigurationBlock
是您自己的类型,或者使用Properties
)。首先,显示您想要在没有流的情况下使用普通switch语句做什么。我认为,当输入顺序无关紧要时,流是理想的。然而,在您的ini示例中,行的顺序是至关重要的。因此,顶级流的元素不应该是文本行,而应该是配置节。每个部分都由顺序不敏感的文本行组成。不幸的是,@MaartenBodewes。。我有点希望有几行代码。哦,是的,这比问题中的switch语句可读性和可维护性更好。你为什么要硬编码这些行的结尾?只是为了确保它不能在Mac或Linux上工作?为什么在路径中使用反斜杠而不是正斜杠?只是为了让你逃离他们?
m.forEach((group,attr)-> {
System.out.println("["+group+"]");
attr.forEach((key,value)->System.out.println(key+"="+value));
});
public class Main {
public static void main(String[] args) throws IOException {
Path path = Paths.get("D:\\Development\\workspace\\Application\\src\\main\\resources\\init.txt");
String content = new String(Files.readAllBytes(path));
Map<String, Config> configMap = Stream.of(content.split("\\n\\r"))
.map(config -> Arrays.asList(config.split("\\r")))
.collect(HashMap<String, Config>::new, (map, list) -> {
String header = list.get(0);
String pos = list.get(1);
String size = list.get(2);
String collapsed = list.get(3);
map.put(header, new Config(pos.substring(pos.indexOf("=") + 1), size.substring(size.indexOf("=") + 1), collapsed.substring(collapsed.indexOf("=") + 1)));
}, (m, u) -> {});
System.out.println(configMap);
}
}
class Config {
public String pos;
public String size;
public String collapsed;
public Config(String pos, String size, String collapsed) {
this.pos = pos;
this.size = size;
this.collapsed = collapsed;
}
@Override
public String toString() {
return "Config{" + "pos='" + pos + '\'' + ", size='" + size + '\'' +
", collapsed='" + collapsed + '\'' + '}';
}
}
{
[Debug]=Config{pos='7,79', size='507,392', collapsed='0'},
[ImGui Demo]=Config{pos='320,5', size='550,680', collapsed='0'}
}
private static <T> Predicate<T> testAndConsume(Predicate<T> pred, Consumer<T> cons) {
return t -> {
boolean result = pred.test(t);
if (result) cons.accept(t);
return result;
};
}
public static class SwitchConsumer<T> {
Predicate<T> conditionalConsumer;
private SwitchConsumer(Predicate<T> pred) {
conditionalConsumer = pred;
}
public static <C> SwitchConsumer<C> inCase(Predicate<C> pred, Consumer<C> cons) {
return new SwitchConsumer<>(testAndConsume(pred, cons));
}
public SwitchConsumer<T> elseIf(Predicate<T> pred, Consumer<T> cons) {
return new SwitchConsumer<>(conditionalConsumer.or(testAndConsume(pred,cons)));
}
public Consumer<T> elseDefault(Consumer<T> cons) {
return testAndConsume(conditionalConsumer.negate(),cons)::test; // ::test converts Predicate to Consumer
}
}
Stream.of("Pos=320,5", "Size=550,680", "Collapsed=0")
.map(s -> s.split("="))
.forEach(SwitchConsumer.<String[]>
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 -> {}));