SnakeYAML 加载到 Guava MultiMap 中
SnakeYAML load into Guava MultiMap
我正在尝试使用 SnakeYAML 将 Yaml 文件加载到 MultiMap 中,但我一直遇到以下异常:java.base/java.util.LinkedHashMap cannot be cast to com.google.common.collect.Multimap
。有什么方法可以高效且有效地将 SnakeYAML 对象加载到 Guava MultiMap 中吗?我知道您可以使用常规 HashMap 来执行此操作,但我的目标 Yaml 具有重复键,因此它需要使用 MultiMap。我在这里先向您的帮助表示感谢。我使用 SnakeYAML 填充 MultiMap 的代码如下:
//Read the config file
InputStream configIn;
try {
configIn = FileUtil.loadFileAsStream(configPath);
//Load the config file into the YAML object
pluginConf = LinkedHashMultimap.create((Multimap<String, Object>) configData.load(configIn));
}
catch(FileNotFoundException e){
// TODO Auto-generated catch block
e.printStackTrace();
}
编辑:具有重复键的示例 YAML
join:
message: "JMessage1"
quit:
message: "QMessage1"
join:
message: "JMessage2"
quit:
message: "QMessage2"
join:
message: "JMessage3"
quit:
message: "QMessage3"
我确实设法解决了这个问题,但我使用了正则表达式和常规 HashMap,而不是像我最初打算的那样使用 Guava Multimap。例如,这是一个具有重复键的 YAML 文件:
join:
message: "JMessage1"
quit:
message: "QMessage1"
join:
message: "JMessage2"
quit:
message: "QMessage2"
为了解析所有消息,我所做的只是简单地向每个重复的父键添加数字(join
变为 join1
,quit
变为 quit1
,等等)。由于每个键中都有一个数字,因此可以使用以下正则表达式将它们轻松还原为仅说 join
或 quit
:在遍历 HashMap 的 for 循环中使用 str.replaceAll("[^a-zA-Z.]", "").toLowerCase()
。由于 HashMap 条目现在在循环中读取为 join
、quit
、join
、quit
,因此可以使用类似以下代码段的内容轻松获取它们的值:
if(entry.equals("join")){
//Do stuff
}
之后,可以将值添加到 ArrayList 或其他集合中。在我的例子中,我使用了一个 ArrayList 并将 YAML 文件的属性分配给一个对象的实例变量。项目中我的 类 之一的以下片段实现了这一点:
//Iterate through the HashMap
for(Entry<?, ?> configEntry : pluginConf.entrySet()){
//Get a string from the selected key that contains only lower-case letters and periods
String entryKey = configEntry.getKey().toString().replaceAll("[^a-zA-Z.]", "").toLowerCase();
//Search for join messages
if(entryKey.equals("messages.join")){
//Get the key name of the current entry
String joinKeyName = configEntry.getKey().toString();
//Create a join message object
JoinMessage newJoinMessage = new JoinMessage(,
configData.getString(joinKeyName + ".message")
);
//Add the join message object to the join message ArrayList
joinMessages.add(newJoinMessage);
//Add to the join message quantity
joinMsgQuantity ++;
}
}
并没有像我最初要求的那样真正使用允许重复的 HashMap,但是这个 "hack" 对我来说完美无缺。希望这可以帮助任何其他想要做这样的事情的人。
我正在尝试使用 SnakeYAML 将 Yaml 文件加载到 MultiMap 中,但我一直遇到以下异常:java.base/java.util.LinkedHashMap cannot be cast to com.google.common.collect.Multimap
。有什么方法可以高效且有效地将 SnakeYAML 对象加载到 Guava MultiMap 中吗?我知道您可以使用常规 HashMap 来执行此操作,但我的目标 Yaml 具有重复键,因此它需要使用 MultiMap。我在这里先向您的帮助表示感谢。我使用 SnakeYAML 填充 MultiMap 的代码如下:
//Read the config file
InputStream configIn;
try {
configIn = FileUtil.loadFileAsStream(configPath);
//Load the config file into the YAML object
pluginConf = LinkedHashMultimap.create((Multimap<String, Object>) configData.load(configIn));
}
catch(FileNotFoundException e){
// TODO Auto-generated catch block
e.printStackTrace();
}
编辑:具有重复键的示例 YAML
join:
message: "JMessage1"
quit:
message: "QMessage1"
join:
message: "JMessage2"
quit:
message: "QMessage2"
join:
message: "JMessage3"
quit:
message: "QMessage3"
我确实设法解决了这个问题,但我使用了正则表达式和常规 HashMap,而不是像我最初打算的那样使用 Guava Multimap。例如,这是一个具有重复键的 YAML 文件:
join:
message: "JMessage1"
quit:
message: "QMessage1"
join:
message: "JMessage2"
quit:
message: "QMessage2"
为了解析所有消息,我所做的只是简单地向每个重复的父键添加数字(join
变为 join1
,quit
变为 quit1
,等等)。由于每个键中都有一个数字,因此可以使用以下正则表达式将它们轻松还原为仅说 join
或 quit
:在遍历 HashMap 的 for 循环中使用 str.replaceAll("[^a-zA-Z.]", "").toLowerCase()
。由于 HashMap 条目现在在循环中读取为 join
、quit
、join
、quit
,因此可以使用类似以下代码段的内容轻松获取它们的值:
if(entry.equals("join")){
//Do stuff
}
之后,可以将值添加到 ArrayList 或其他集合中。在我的例子中,我使用了一个 ArrayList 并将 YAML 文件的属性分配给一个对象的实例变量。项目中我的 类 之一的以下片段实现了这一点:
//Iterate through the HashMap
for(Entry<?, ?> configEntry : pluginConf.entrySet()){
//Get a string from the selected key that contains only lower-case letters and periods
String entryKey = configEntry.getKey().toString().replaceAll("[^a-zA-Z.]", "").toLowerCase();
//Search for join messages
if(entryKey.equals("messages.join")){
//Get the key name of the current entry
String joinKeyName = configEntry.getKey().toString();
//Create a join message object
JoinMessage newJoinMessage = new JoinMessage(,
configData.getString(joinKeyName + ".message")
);
//Add the join message object to the join message ArrayList
joinMessages.add(newJoinMessage);
//Add to the join message quantity
joinMsgQuantity ++;
}
}
并没有像我最初要求的那样真正使用允许重复的 HashMap,但是这个 "hack" 对我来说完美无缺。希望这可以帮助任何其他想要做这样的事情的人。