Я новичок в java, пытаюсь найти способ сделать это лучше. Возможно использование регулярного выражения.
String text = test.get(i).toString()
// text looks like this in string form:
// EnumOption[enumId=test,id=machine]
String checker = text.replace("[","").replace("]","").split(",")[1].split(" = ")[1];
// checker becomes machine
Моя цель — разобрать эту text
строку и просто вернуться обратно machine
. Что я и сделал в приведенном выше коде.
Но это выглядит некрасиво. Мне было интересно, какое регулярное выражение можно использовать здесь, чтобы сделать это немного лучше? Или, может быть, другое предложение?
String checker = text.replaceFirst("EnumOption\\[enumId=test,id=(.*)\\]", "$1");
а нет ли более простого варианта вроде test.get(i).getId()
?
Что такое test
? Как сказал Хольгер, нельзя ли получить идентификатор объекта напрямую, минуя обходной путь через toString()
?
@Holger, я на 100% согласен с тобой, но в Eclipse, когда я пытался это сделать. .getId() не вариант. Я мало знаю о java. Я просто предположил, что если Eclipse не показывает его доступным, то он недоступен.
test — это customTypedList, и я перебираю его, перебирая каждый элемент. и каждый элемент является enumOption
Конечно, регулярное выражение можно использовать, но иногда оно менее производительно, менее читабельно и более подвержено ошибкам.
Я бы посоветовал вам не использовать никакие регулярные выражения, которые вы не придумали сами, или, по крайней мере, полностью не понимаете.
PS: я думаю, что ваше решение на самом деле вполне читабельно.
Вот еще одна версия без регулярных выражений:
String text = "EnumOption[enumId=test,id=machine]";
text = text.substring(text.lastIndexOf('=') + 1);
text = text.substring(0, text.length() - 1);
Не делаю вам одолжения, но отрицательный голос причиняет боль, так что вот:
String input = "EnumOption[enumId=test,id=machine]";
Matcher matcher = Pattern.compile("EnumOption\\[enumId=(.+),id=(.+)\\]").matcher(input);
if (!matcher.matches()) {
throw new RuntimeException("unexpected input: " + input);
}
System.out.println("enumId: " + matcher.group(1));
System.out.println("id: " + matcher.group(2));
Когда вы говорите о производительности, мне интересно, почему вы без необходимости выполняете две substring
операции вместо одной text.substring(text.lastIndexOf('=') + 1, text.length() - 1)
Я не имел в виду, что моя версия более производительна. Я обычно оптимизирую для удобочитаемости и скорости реализации. Это был скорее общий комментарий.
Итак, вы думаете, что выполнение двух операций substring
вместо одной делает код более читабельным?
Не на самом деле нет. Примерно так же просто, как собственное решение ОП. Читаемый, простой для понимания и пошаговый с отладчиком.
int start = text.lastIndexOf("id = "); int end = text.length() - 1; text = text.substring(start, end);
Почему это не более читабельно, чем две подстроки?
@OlivierGrégoire Возможно, это даже более читабельно. Я чувствую себя очень неправильно понятым. Я пытался сказать, что любое решение, не связанное с регулярными выражениями, часто быстрее реализуется, его легче понять и поддерживать.
Используйте поиск назад регулярного выражения:
(?<=\bid=)[^],]*
(?<= ) // Start matching only after what matches inside
\bid= // Match "\bid = " (= word boundary then "id = "),
[^],]* // Match and keep the longest sequence without any ']' or ','
В Java используйте это так:
import java.util.regex.*;
class Main {
public static void main(String[] args) {
Pattern pattern = Pattern.compile("(?<=\\bid=)[^],]*");
Matcher matcher = pattern.matcher("EnumOption[enumId=test,id=machine]");
if (matcher.find()) {
System.out.println(matcher.group(0));
}
}
}
Это приводит к
machine
Предполагая, что вы используете Polarion ALM API, вы должны использовать метод EnumOption
getId вместо депарсинга и повторного анализа значения через строку:
String id = test.get(i).getId();
Использование функций замены и разделения не учитывает структуру данных.
Если вы хотите использовать регулярное выражение, вы можете просто использовать группу захвата без каких-либо обходов, где enum может быть любым значением, кроме ]
и запятой, а id может быть любым значением, кроме ]
.
Значение id будет в группе захвата 1.
\bEnumOption\[enumId=[^=,\]]+,id=([^\]]+)\]
Объяснение
\bEnumOption
Соответствие EnumOption
, которому предшествует граница слова\[enumId=
Матч [enumId=
[^=,\]]+,
Совпадение 1+ раз с любым символом, кроме =
,
и ]
id=
Совпадение буквально(
Группа захвата 1
[^\]]+
Совпадение 1+ раз с любым символом, кроме ]
)\]
Демонстрация регулярных выражений | Демонстрация Java
Pattern pattern = Pattern.compile("\\bEnumOption\\[enumId=[^=,\\]]+,id=([^\\]]+)\\]");
Matcher matcher = pattern.matcher("EnumOption[enumId=test,id=machine]");
if (matcher.find()) {
System.out.println(matcher.group(1));
}
Выход
machine
Если может быть больше значений, разделенных запятыми, вы также можете сопоставлять id только с использованием отрицательных классов символов [^][]*
до и после сопоставления id, чтобы оставаться в пределах квадратных скобок.
\bEnumOption\[[^][]*\bid=([^,\]]+)[^][]*\]
В Яве
String regex = "\\bEnumOption\\[[^][]*\\bid=([^,\\]]+)[^][]*\\]";
Для уточнения: хотите ли вы получить строку, написанную после
id=
, независимо от следующей строки?