当前问题陈述的输入是 -
INPUT.TXT
#START_OF_TEST_CASES
#DATA
key1:VA1
key2:VA2
key3:VA3
key4:VA4
key5:VA5
#DEND
#ENTRIES:
1{key1}{key1}{key3}
2{key2}{key2}{key1}
3{key3}{key1}{key2}
#EEND
现在我想读取这个文件并在#DATA和#DEND之间创建一行HashMap。 HashMap的键是':'的左侧部分,值是右侧部分。虽然我们可以迭代地实现这一点,但我想使用Java 8的Stream API来实现这一点。
不幸的是,Java 8流不支持两次匹配之间的元素提取。在Java 9中,您可以使用
Map<String,String> map;
try(Stream<String> stream = Files.lines(path)) {
map = stream
.dropWhile(s -> !s.equals("#DATA")).skip(1)
.takeWhile(s -> !s.equals("#DEND"))
.filter(Pattern.compile("^[^#].*:").asPredicate())
.map(item -> item.split(":", 2))
.collect(Collectors.toMap(parts->parts[0], parts->parts[1]));
}
// use the map
map.forEach((k,v)->System.out.println(k+" -> "+v));
dropWhile
将在第一个匹配元素之前删除所有元素,skip(1)
将跳过匹配元素,takeWhile
在第一个元素匹配结束条件后有效地删除所有元素。
使用filter
模式的下一个^[^#].*:
步骤将跳过以#
开头或不包含:
的所有行。剩下的步骤很简单。当指定2
到split
的限制时,它不会在遇到第一个:
后搜索后续的:
s。
在Java 8下,可以在流操作之前使用Scanner
实现在两个匹配之间提取部分:
String part;
try(Scanner s = new Scanner(path)) {
part = s.findWithinHorizon("(?<=\\R#DATA\\R)(.|\\R)*(?=\\R#DEND\\R)", 0);
}
Map<String,String> map = Pattern.compile("\\R").splitAsStream(part)
.filter(Pattern.compile("^[^#].*:").asPredicate())
.map(item -> item.split(":", 2))
.collect(Collectors.toMap(parts->parts[0], parts->parts[1]));
// use the map
map.forEach((k,v)->System.out.println(k+" -> "+v));
如果您看到#DATA和#DEND之间的谎言包含':',那么我想出了以下解决方案 -
File file = new File("Input.txt");
try {
Map<String,String> map = Files.lines(file.toPath())
.filter(list -> list.contains(":"))
.map(item -> item.split(":"))
.filter(arr -> arr.length > 1)
.collect(Collectors.toMap(parts->parts[0], parts->parts[1]));
System.out.println(map.values());
} catch (IOException e) {
e.printStackTrace();
}
上面的代码首先只过滤包含冒号':'的行,然后根据冒号拆分这些行,之后,我们只过滤长度大于1的列表,因为如果你仔细看到input.txt文件,你可以找到“#ENTRIES:”包含冒号,但在此之后不包含任何字符。获得所需数据后,我们创建HashMap。
以下代码模式可以解决您的问题:
List<String> lines = Files.readAllLines(Paths.get("Input.txt"));
int from = lines.indexOf("#DATA") + 1;
int to = lines.indexOf("#DEND");
Map<String, String> map = lines.stream()
.skip(from)
.limit(to - from)
.map(s -> s.split(":"))
.collect(Collectors.toMap(pair -> pair[0], pair -> pair[1]));