我有數據從腳本來,其通常是這樣的線(單線示例):解析一行數據:分裂VS正則表達式
1234567890;group1;varname1;133333337;prop1=val1;prop2=val2;prop3=val3
我需要打破各行成關鍵值的項目對於Map來說,每個項目由分隔符字符串分隔(示例中的;
,但它也可以是自定義的)。前4個項目是靜態的,這意味着只有值在行中,並且鍵已知。其餘的是鍵值項目的可變數量(0或更多key=value
塊)。 請首先看看下面的輸出給你一個想法。
我已經有兩種工作方法來完成這項工作,其中兩者都爲同一行拋出相同的輸出。出於好奇,我設立了一個測試課來演示這兩種方法以及一些(簡單的)性能分析。 請注意無效的輸入處理在下面顯示的方法中是最小的。 (使用Apache共享)
字符串分割:
private static List<String> splitParsing(String dataLine, String separator) {
List<String> output = new ArrayList<String>();
long begin = System.nanoTime();
String[] data = StringUtils.split(dataLine, separator);
if (data.length >= STATIC_PROPERTIES.length) {
// Static properties (always there).
for (int i = 0; i < STATIC_PROPERTIES.length; i++) {
output.add(STATIC_PROPERTIES[i] + " = " + data[i]);
}
// Dynamic properties (0 or more).
for (int i = STATIC_PROPERTIES.length; i < data.length; i++) {
String[] fragments = StringUtils.split(data[i], KEYVALUE_SEPARATOR);
if (fragments.length == 2) {
output.add(fragments[0] + " = " + fragments[1]);
}
}
}
long end = System.nanoTime();
output.add("Execution time: " + (end - begin) + "ns");
return output;
}
正則表達式(使用JDK 1.6):
private static List<String> regexParsing(String dataLine, String separator) {
List<String> output = new ArrayList<String>();
long begin = System.nanoTime();
Pattern linePattern = Pattern.compile(StringUtils.replace(DATA_PATTERN_TEMPLATE, SEP, separator));
Pattern propertiesPattern = Pattern.compile(StringUtils.replace(PROPERTIES_PATTERN_TEMPLATE, SEP, separator));
Matcher lineMatcher = linePattern.matcher(dataLine);
if (lineMatcher.matches()) {
// Static properties (always there).
for (int i = 0; i < STATIC_PROPERTIES.length; i++) {
output.add(STATIC_PROPERTIES[i] + " = " + lineMatcher.group(i + 1));
}
Matcher propertiesMatcher = propertiesPattern.matcher(lineMatcher.group(STATIC_PROPERTIES.length + 1));
while (propertiesMatcher.find()) {
output.add(propertiesMatcher.group(1) + " = " + propertiesMatcher.group(2));
}
}
long end = System.nanoTime();
output.add("Execution time: " + (end - begin) + "ns");
return output;
}
主要方法:
public static void main(String[] args) {
String input = "1234567890;group1;varname1;133333337;prop1=val1;prop2=val2;prop3=val3";
System.out.println("Split parsing:");
for (String line : splitParsing(input, ";")) {
System.out.println(line);
}
System.out.println();
System.out.println("Regex parsing:");
for (String line : regexParsing(input, ";")) {
System.out.println(line);
}
}
常量:
// Common constants.
private static final String TIMESTAMP_KEY = "TMST";
private static final String GROUP_KEY = "GROUP";
private static final String VARIABLE_KEY = "VARIABLE";
private static final String VALUE_KEY = "VALUE";
private static final String KEYVALUE_SEPARATOR = "=";
private static final String[] STATIC_PROPERTIES = { TIMESTAMP_KEY, GROUP_KEY, VARIABLE_KEY, VALUE_KEY };
// Regex constants.
private static final String SEP = "{sep}";
private static final String PROPERTIES_PATTERN_TEMPLATE = SEP + "(\\w+)" + KEYVALUE_SEPARATOR + "(\\w+)";
private static final String DATA_PATTERN_TEMPLATE = "(\\d+)" + SEP + "(\\w+)" + SEP + "(\\w+)" + SEP + "(\\d+\\.?\\d*)"
+ "((?:" + PROPERTIES_PATTERN_TEMPLATE + ")*)";
從主要的方法
輸出:
Split parsing:
TMST = 1234567890
GROUP = group1
VARIABLE = varname1
VALUE = 133333337
prop1 = val1
prop2 = val2
prop3 = val3
Execution time: 8695796ns
Regex parsing:
TMST = 1234567890
GROUP = group1
VARIABLE = varname1
VALUE = 133333337
prop1 = val1
prop2 = val2
prop3 = val3
Execution time: 1250787ns
從輸出來看(我跑多次),似乎正則表達式的方法是在性能方面更有效,儘管我最初的想法朝着更分裂方法。但是,我不確定這種性能分析的代表性如何。
我的問題是:
- 這兩個方法將是最好的或更易於使用無效輸入處理? (例如:靜態項目丟失,格式無效等)。
- 哪種方法不太可能產生意想不到的行爲?
- 爲什麼正則表達式方法更快?我會假設相反,因爲
Matcher
s和Pattern
必須有一個更復雜的邏輯背後。我的表現分析是否具有代表性?
考慮到'System.out.println'的調用,我會擔心報告的持續時間的有效性。將文本收集到某種字符串生成器並在'end = System.nanoTime();'後面打印可能會更好。 – AdrianHHH
確實!原始上下文中的代碼將解析的項目添加到「List」中,我將使用該行爲調整上面的代碼。 –
@AdrianHHH我用你的建議編輯了這個問題。 –