簡體   English   中英

從Java列表中提取子字符串

[英]Extracting Substrings from a List in Java

如果我有一個父字符串(我們稱其為output ),其中包含諸如此類的變量分配列表...

status.availability-state available
status.enabled-state enabled
status.status-reason The pool is available

我想提取給定變量名的列表中每個變量的值,即status.availability-statestatus.enabled-statestatus.status-reason后面的空格之后的子字符串,這樣我最終得到三種不同的變量賦值,使以下每個String比較都為真...

String availability = output.substring(TODO);
String enabled = output.substring(TODO);
String reason = output.substring(TODO);

availability.equals("available");
enabled.equals("enabled");
reason.equals("The pool is available");

最簡單的方法是什么? 我是否應該為此使用substring

這有點棘手,因為您需要將值分配給特定的變量-您不能只擁有Java中變量的鍵映射。

我會考慮通過一個開關來做到這一點:

for (String line : output.split('\n')) {
  String[] frags = line.split(' ', 2);  // Split the line in 2 at the space.
  switch (frags[0]) {  // This is the "key" of the variable.
    case "status.availability-state":
      availability = frags[1];  // This assigns the "value" to the relevant variable.
      break;
    case "status.enabled-state":
      enabled = frags[1];
      break;
    // ... etc
  }
}

它不是很漂亮,但是您沒有太多選擇。

這里似乎有兩個問題-如何解析字符串,以及如何通過名稱分配變量。

解決字符串,一次解析一個步驟:

  • 首先編寫一個程序,一次讀取一行,然后在循環體內輸出每一行。 String.split()StringTokenizer是此處的兩個選項。
  • 接下來,通過編寫處理一行的方法來增強此功能。 相同的工具在這里有用,有助於分割空格。
  • 現在,您應該有一個可以打印name: status.availability-state, value: available的程序name: status.availability-state, value: available用於每一行輸入。

接下來,您要根據參數名稱以編程方式分配給變量。

沒有合法的方法可以在運行時查看變量的名稱(好的,Java 8反射有很多方法,但是沒有充分的理由不應該使用它)。

因此,最好的辦法是使用switchif語句:

switch(name) {
    case status.availability-state:
        availability = value;
        break;
    ... etc.
}

但是,無論何時使用switchif應該考慮是否有更好的方法。

有什么理由不能將這些變量轉換為Map條目?

 configMap.add(name,value);

然后閱讀:

 doSomethingWith(configMap.get("status.availability");

那就是地圖的用途。 使用它們。

這與新手錯誤類似,即使用名為person1person2person3 ...的變量而不是使用數組。 最終,他們問:“我如何從25號變成可變人person25 ?” -答案是,雖然不能,但是使用數組或列表很容易。 people[number]people.get(number)

一個有效的替代方法是將字符串除以\\n並添加到Map 例:

String properties = "status.availability-state available\nstatus.enabled-state enabled\nstatus.status-reason The pool is available";

Map<String, String> map = Arrays.stream(properties.split("\n"))
                    .collect(Collectors.toMap(s -> s.split(" ")[0], s -> s.split(" ", 2)[1]));

System.out.println(map.get("status.status-reason"));

應該輸出The pool is available

此循環將匹配並提取變量,然后您可以根據需要分配它們:

Pattern regex = Pattern.compile("status\\.(.*?)-.*? ([a-z]+)");
Matcher matcher = regex.matcher(output);
while (matcher.find()) {
    System.out.println(matcher.group(1) + "=" + matcher.group(2));
}

status\\\\. 匹配“狀態”。

(.*?)匹配任何字符序列但不是貪婪的字符並捕獲它們

-.*匹配破折號,任意字符,空格

([az]+)匹配任何小寫字母字符串,並捕獲它們

這是一種實現方法:

Map<String, String> properties = getProperties(propertiesString);

availability = properties.get("availability-state");
enabled = properties.get("enabled-state");
reason = properties.get("status-reason");

// ...

public void getProperties(String input) {
    Map<String, String> properties = new HashMap<>();
    String[] lines = output.split("\n");

    for (String line : lines) {
        String[] parts = line.split(" ");
        int keyStartIndex = parts[0].indexOf(".") + 1;
        int spaceIndex = parts[1].indexOf(" ");
        string key = parts[0].substring(keyStartIndex, spaceIndex);
        properties.put(key, parts[1]);
    }

    return properties;
}

就設置這些值的代碼而言,這似乎更簡單一些,因為每個值都被設置為與映射中的值完全相同,而不是遍歷某些字符串列表並查看其是否包含特定值在此基礎上做不同的事情。

設計這種方法的主要用例是在運行時在內存中創建字符串。 如果屬性是在外部文件中創建的,則此代碼仍然可以工作(在內存中創建所需的String之后),但是最好使用Properties文件或Scanner

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM