如何在Java中搜索一串键/值对

时间:2012-03-13 01:53:43

标签: java regex string-matching

我有一个格式如下的字符串:

"key1=value1;key2=value2;key3=value3"

任意数量的键/值对。

我需要检查某个键是否存在(假设它叫做“特殊键”)。如果是,我想要与之相关的值。如果有多个“特殊键”设置,我只想要第一个。

现在,我正在寻找“特殊键”的索引。我从该索引处开始一个子字符串,然后查找第一个=字符的索引。然后我查找第一个;字符的索引。这两个索引之间的子字符串给出了与“特殊键”相关联的值。

这不是一个优雅的解决方案,它真的很困扰我。找到与“特殊键”对应的值的优雅方法是什么?

10 个答案:

答案 0 :(得分:10)

我会将String解析为一个映射,然后检查密钥:

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

答案 1 :(得分:8)

使用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 :(得分:5)

如果它只是您所关注的一个键,您可以使用正则表达式\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));
}

如果您正在使用其他键执行某些操作,请在循环中拆分;然后= - 不需要正则表达式。

答案 3 :(得分:2)

如果有人对纯正的基于Regex的方法感兴趣,以下代码段可以正常工作。

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时,您的生活不应该复杂化。

答案 4 :(得分:1)

有很多方法可以做到这一点。也许最简单的方法是使用 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]

答案 5 :(得分:1)

这可以使用 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]

答案 6 :(得分:0)

Regex非常适合同时进行匹配和解析:

//c#
string input = @"key1=value1;specialkey=scott;key3=value3";
var specialkey = Regex.Match(input, "specialkey=(.*?);").Groups[1].Value;
Console.WriteLine(specialkey);

答案 7 :(得分:0)

尝试:(?:(?: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)) );
            }
        }
    }
}

答案 8 :(得分:0)

使用基本过滤器:使用 [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;
        
}

答案 9 :(得分:0)

试试这个:

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