如何在 Java 中搜索一串键/值对
Posted
技术标签:
【中文标题】如何在 Java 中搜索一串键/值对【英文标题】:How to search a string of key/value pairs in Java 【发布时间】:2012-03-29 11:01:28 【问题描述】:我有一个格式如下的字符串:
"key1=value1;key2=value2;key3=value3"
适用于任意数量的键/值对。
我需要检查某个键是否存在(假设它称为“特殊键”)。如果是这样,我想要与之关联的值。如果设置了多个“特殊键”,我只想要第一个。
现在,我正在寻找“specialkey”的索引。我从该索引开始获取一个子字符串,然后查找第一个 =
字符的索引。然后我寻找第一个;
字符的索引。这两个索引之间的子字符串给了我与“specialkey”相关的值。
这不是一个优雅的解决方案,它真的让我很困扰。找到与“specialkey”对应的值的优雅方法是什么?
【问题讨论】:
请注意,这篇文章中的一些答案是从Extracting values corresponding to a certain "key" from a string List in Java 合并而来的,Arrays.asList("A=1,B=2,C=3","A=11,B=12,C=13,D=15",...
具有特定的键和值
【参考方案1】:
使用String.split:
String[] kvPairs = "key1=value1;key2=value2;key3=value3".split(";");
这将为您提供一个包含以下元素的数组kvPairs
:
key1=value1
key2=value2
key3=value3
遍历这些并拆分它们:
for(String kvPair: kvPairs)
String[] kv = kvPair.split("=");
String key = kv[0];
String value = kv[1];
// Now do with key whatever you want with key and value...
if(key.equals("specialkey"))
// Do something with value if the key is "specialvalue"...
【讨论】:
【参考方案2】:如果它只是您所追求的一键,您可以使用正则表达式 \bspecialkey=([^;]+)(;|$)
并提取捕获组 1:
Pattern p = Pattern.compile("\\bspecialkey=([^;]+)(;|$)");
Matcher m = p.matcher("key1=value1;key2=value2;key3=value3");
if (m.find())
System.out.println(m.group(1));
如果您正在使用其他键做某事,则在循环中拆分 ;
和 =
- 不需要正则表达式。
【讨论】:
请注意 string.split 的答案不仅是迟钝的,而且在您输入复杂性的第一个提示时它们开始分解(例如您需要一次匹配多个键,或者一个键没有其中的某个子字符串)。维护或更改也是一场噩梦,而这一点轻而易举。【参考方案3】:我会将字符串解析为映射,然后只检查键:
String rawValues = "key1=value1;key2=value2;key3=value3";
Map<String,String> map = new HashMap<String,String>();
String[] entries = rawValues.split(";");
for (String entry : entries)
String[] keyValue = entry.split("=");
map.put(keyValue[0],keyValue[1]);
if (map.containsKey("myKey"))
return map.get("myKey");
【讨论】:
【参考方案4】:以防万一有人对纯正则表达式方法感兴趣,以下 sn-p 有效。
Pattern pattern = Pattern.compile("([\\w]+)?=([\\w]+)?;?");
Matcher matcher = pattern.matcher("key1=value1;key2=value2;key3=value3");
while (matcher.find())
System.out.println("Key - " + matcher.group(1) + " Value - " + matcher.group(2);
输出将是
Key - key1 Value - value1
Key - key2 Value - value2
Key - key3 Value - value3
但是,正如其他人之前解释的那样,建议在任何一天使用String.split()
来执行此类任务。当有替代方法时,您不应该尝试使用 Regex 使您的生活复杂化。
【讨论】:
【参考方案5】:试试看:(?:(?:A=)([^,]*))
演示:https://regex101.com/r/rziGDz/1
否则,您使用正则表达式和您的列表找到代码以获得答案:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.*;
public class Main
public static void main(String[] args)
List<Integer> results = new ArrayList();
Pattern pattern = Pattern.compile("(?:(?:A=)([^,]*))", Pattern.CASE_INSENSITIVE);
List<String> OriginalList = Arrays.asList(
"A=1,B=2,C=3",
"A=11,B=12,C=13,D=15",
"A=5,B=4,C=9,D=10,E=13",
"A=19,B=20,C=91,D=40,E=33",
"A=77,B=27,C=37");
for (int i = 0; i < OriginalList.size(); i++)
Matcher matcher = pattern.matcher(OriginalList.get(i));
boolean matchFound = matcher.find();
if(matchFound)
System.out.println( matcher.group(1) );
results.add( Integer.parseInt(matcher.group(1)) );
【讨论】:
【参考方案6】:使用基本过滤器:使用[A-Z=,]+
正则表达式进行拆分。选择第二个元素。
public List filter()
List<String> originalList = Arrays.asList("A=1,B=2,C=3", "A=11,B=12,C=13,D=15", "A=5,B=4,C=9,D=10,E=13",
"A=19,B=20,C=91,D=40,E=33", "A=77,B=27,C=37");
List<Integer> parsedData = new ArrayList();
for(String str: originalList)
Integer data = Integer.parseInt(str.split("[A-Z=,]+")[1]);
parsedData.add(data);
return parsedData;
【讨论】:
您可以从您的角色类别中删除^
。它仅适用于否定整个类,当它被放置为类中的第一个字符时,或者它被视为另一个字符。目前,字符串被拆分为:=
、^
或 ,
。如果它没有在,
处拆分,则结果字符串数组中的第二个元素将是1,B
,当尝试将其解析为Integer
时,这将导致java.lang.NumberFormatException
。你可以用System.out.println(Arrays.toString(str.split("[=^,]")));
检查我是否正确
str.split("[=^,]") 返回一个字符串数组,如 s[0]=A, s[1]=1, s[2]=B ... .从这个字符串数组中,我选择索引 1 的值并将其解析为整数)。在 github repo 中,我写了更多细节 -github.com/khabib97/***-Responses/blob/main/…
我知道它会返回什么。我尝试过这个。不带 ^ 试试。它返回完全相同的东西。 “和排除”究竟是什么意思?
谢谢。这是我的错误。我更正了。【参考方案7】:
试试这个:
List<Integer> results = new ArrayList();
Pattern p = Pattern.compile("(?:(?:A=)([^,]*))");
Matcher m = null;
for (String tmp : OriginalList)
m = p.matcher(tmp);
if (m.find())
int r = Integer.parseInt(m.group(0).replace("A=", ""));
results.add(r);
【讨论】:
我想m
是Matcher
。 p
是 Pattern
。 compile()
使用了什么正则表达式?您可以添加其余的代码吗?如果你能解释它也会有所帮助。 “试试这个”不是很有帮助。
哦,是的!也许复制代码或合并某些东西会破裂。固定!
请注意,这篇文章已合并到另一个问题中。也许您想更新它或添加与您的特定正则表达式相关的键/值。如果您解释了您正在使用的正则表达式,这也会有所帮助。当您使用group(1)
捕获值时,为什么要使用group(0)
然后删除A=
?【参考方案8】:
有很多方法可以做到这一点。也许最简单的是使用 Streams API(Java 8 及更高版本可用)来处理匹配结果:
List<String> OriginalList = Arrays.asList("A=1,B=2,C=3",
"A=11,B=12,C=13,D=15", "A=5,B=4,C=9,D=10,E=13",
"A=19,B=20,C=91,D=40,E=33", "A=77,B=27,C=37");
这会流式传输字符串
匹配模式并提取整数
收集到列表
Pattern p = Pattern.compile("A=(\\d+)");
List<Integer> result = OriginalList.stream().
flatMap(str->p.matcher(str).results())
.map(mr->Integer.valueOf(mr.group(1)))
.collect(Collectors.toList());
System.out.println(result);
打印:
[1, 11, 5, 19, 77]
【讨论】:
Matcher::results
提供 Stream<MatchResult>
自 Java 9 起可用【参考方案9】:
这可以使用 Stream API 来实现,方法是用逗号和Stream::flatMap
简单地分割输入列表中的每个字符串
// assuming A is not always at the beginning
List<String> list = Arrays.asList(
"A=1,B=2,C=3",
"A=11,B=12,C=13,D=15",
"A=5,B=4,C=9,D=10,E=13",
"B=20,C=91,D=40,E=33",
"B=27, A=19, C=37, A=77");
List<Integer> aNums = list.stream() // Stream<String>
.flatMap(
s -> Arrays.stream(s.split("\\s*,\\s*")) // Stream<String> pairs of letter=digits
.filter(pair -> pair.startsWith("A="))
.map(pair -> Integer.valueOf(pair.substring(2)))
)
.collect(Collectors.toList());
System.out.println(aNums);
输出:
[1, 11, 5, 19, 77]
更新
拆分输入字符串并仅保留与A
相关的数字的模式可以应用如下:
Pattern splitByA = Pattern.compile("A\\s*=\\s*|\\s*,\\s*|[^A]\\s*=\\s*\\d+");
List<Integer> aNums2 = list.stream()
.flatMap(splitByA::splitAsStream) // Stream<String>
.filter(Predicate.not(String::isEmpty)) // need to remove empty strings
.map(Integer::valueOf)
.collect(Collectors.toList());
System.out.println(aNums2);
输出是一样的
[1, 11, 5, 19, 77]
【讨论】:
以上是关于如何在 Java 中搜索一串键/值对的主要内容,如果未能解决你的问题,请参考以下文章
java - 如何在java中使用布尔值对ArrayLists进行排序?