简体   繁体   English

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

[英]How to search a string of key/value pairs in Java

I have a String that's formatted like this:我有一个格式如下的字符串:

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

for any number of key/value pairs.对于任意数量的键/值对。

I need to check that a certain key exists (let's say it's called "specialkey").我需要检查某个键是否存在(假设它被称为“特殊键”)。 If it does, I want the value associated with it.如果是这样,我想要与之关联的值。 If there are multiple "specialkey"s set, I only want the first one.如果设置了多个“specialkey”,我只想要第一个。

Right now, I'm looking for the index of "specialkey".现在,我正在寻找“specialkey”的索引。 I take a substring starting at that index, then look for the index of the first = character.我取一个从该索引开始的子字符串,然后查找第一个=字符的索引。 Then I look for the index of the first ;然后我寻找第一个的索引; character.特点。 The substring between those two indices gives me the value associated with "specialkey".这两个索引之间的子字符串为我提供了与“specialkey”相关的值。

This is not an elegant solution, and it's really bothering me.这不是一个优雅的解决方案,它真的困扰着我。 What's an elegant way of finding the value that corresponds with "specialkey"?找到与“specialkey”对应的值的优雅方法是什么?

I would parse the String into a map and then just check for the key:我会将字符串解析为映射,然后只检查键:

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

Use String.split :使用String.split

String[] kvPairs = "key1=value1;key2=value2;key3=value3".split(";");

This will give you an array kvPairs that contains these elements:这将为您提供一个包含以下元素的数组kvPairs

key1=value1
key2=value2
key3=value3

Iterate over these and split them, too:迭代这些并拆分它们:

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"...
   }
}

If it's just the one key you're after, you could use regex \\bspecialkey=([^;]+)(;|$) and extract capturing group 1:如果它只是您想要的一个键,则可以使用正则表达式\\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));
}

If you're doing something with the other keys, then split on ;如果您正在使用其他键执行某些操作,则拆分; and then = within a loop - no need for regex.然后=在循环中 - 不需要正则表达式。

Just in case anyone is interested in a pure Regex-based approach, the following snippet works.以防万一有人对基于正则表达式的纯方法感兴趣,以下代码段有效。

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

Output will be输出将是

Key - key1 Value - value1
Key - key2 Value - value2
Key - key3 Value - value3

However, as others explained before, String.split() is recommended any day for this sort of task.但是,正如其他人之前解释的那样,对于此类任务,建议在任何一天使用String.split() You shouldn't complicate your life trying to use Regex when there's an alternative to use.当有替代使用时,您不应该尝试使用 Regex 使您的生活复杂化。

There are many ways to do this.有很多方法可以做到这一点。 Perhaps the simplest is to use the Streams API (available as of Java 8 and later) to process the match results:也许最简单的方法是使用 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");
  • this streams the strings这会传输字符串
  • matches on the pattern and extracts the integer匹配模式并提取整数
  • the collects to a list收集到列表
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);

Prints:印刷:

[1, 11, 5, 19, 77]

This may be implemented using Stream API by simple splitting of each string in the input list by comma and Stream::flatMap这可以使用 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);

Output:输出:

[1, 11, 5, 19, 77]

Update更新
A pattern to split an input string and keep only the digits related to A may be applied as follows:可以按如下方式应用拆分输入字符串并仅保留与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);

Output is the same输出是一样的

[1, 11, 5, 19, 77]

Try : (?:(?:A=)([^,]*))试试 : (?:(?:A=)([^,]*))

Demo : https://regex101.com/r/rziGDz/1演示: https : //regex101.com/r/rziGDz/1

Else you find a code using regex and your list to get answer :否则,您会使用正则表达式和您的列表找到代码以获得答案:

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

Using basic filter: Split using [AZ=,]+ regex.使用基本过滤器:使用[AZ=,]+正则表达式拆分。 Pick the 2nd element.选择第二个元素。

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

Try this:试试这个:

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

Regex is well suited to matching and parsing at the same time: Regex非常适合同时进行匹配和解析:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM