![](/img/trans.png)
[英]ChangeListener in JavaFX: how can I make these generics parameters less ugly?
[英]How do I turn a conditional chain into faster less ugly code?
我有9種不同的語法。 其中一個將根據要解析的文件上txt的第一行加載。
我正在考慮將詞法分析器/解析器生成為sep。 類,然后在我獲得比賽后立即實例化它們-不知道這是否會使我慢下來。 我想應該進行一些基准測試。
確實, 速度絕對是我在這里的目標,但是我知道這是丑陋的代碼。
現在,代碼看起來像這樣:
sin.mark(0)
site = findsite(txt)
sin.reset()
if ( site == "site1") {
loadlexer1;
loadparser1;
} else if (site == "site2") {
loadlexer2;
loadparser2;
}
.................
} else if (site == "site8") {
loadparser8;
loadparser8;
}
findsite(txt) {
...................
if line.indexOf("site1-identifier") {
site = site1;
} else if(line.indexOf("site2-identifier") {
site = site2;
} else if(line.indexOf("site3-identifier") {
site = site3;
}
.........................
} else if(line.indexOf("site8-identifier") {
site = site8;
}
}
一些澄清
1)是的,我確實有9個使用antlr構建的不同語法,因此它們都將具有自己的詞法分析器/解析器objs。
2)是的,截至目前,我們正在比較字符串,並且很明顯,它將被某種整數映射代替。 我還考慮過將站點標識符粘貼到一個正則表達式中,但是我認為這不會加快任何速度。
3)是的,這是偽代碼,因此在這里我不會太挑剔。
4)kdgregory是正確的,因為我無法創建一個詞法分析器/解析器對的實例
我喜歡散列的想法,使代碼看起來更好一點,但是我認為這不會加快我的速度 。
標准方法是使用Map將密鑰字符串連接到將處理它們的詞法分析器:
Map<String,Lexer> lexerMap = new HashMap<String,Lexer>();
lexerMap.put("source1", new Lexer01());
lexerMap.put("source2", new Lexer02());
// and so on
一旦檢索到標識要使用的詞法分析器的字符串,就可以從Map中檢索它,如下所示:
String grammarId = // read it from a file, whatever
Lexer myLexer = lexerMap.get(grammarId);
但是,您的示例代碼有一些怪癖。 首先,indexOf()調用指示您沒有獨立的字符串,並且Map不會在字符串內部查找。 因此,您需要某種方法從讀取的任何字符串中提取實際密鑰。
其次,詞法分析器和解析器通常維護狀態,因此您將無法創建單個實例並重用它。 這表明您需要創建一個工廠類,並將其存儲在地圖中(這是“抽象工廠”模式)。
如果您期望有很多不同的詞法分析器/解析器,則使用映射驅動的方法是有意義的。 對於較小的數字,if-else鏈可能是最好的選擇,並進行適當封裝(這是Factory Method模式)。
幾乎可以肯定,使用多態比字符串操作要快,並且在編譯時會檢查其正確性。 site
真的是字符串嗎? 如果是這樣,則FindSite應該稱為GetSiteName。 我希望FindSite返回一個知道適當的詞法分析器和解析器的Site
對象。
另一個速度問題是編碼速度。 在單個類中擁有不同的詞法分析器和解析器肯定會更好(也許在另一個類中具有共享功能)。 這將使您的代碼略小一些,並且使他人易於理解。
就像是:
Map<String,LexerParserTuple> lptmap = new HashMap<String,LexerParserTuple>(); lpt=lptmap.get(site) lpt.loadlexer() lpt.loadparser()
結合一些正則表達式魔術而不是string.indexOf()來獲取站點名稱,應該可以極大地清理代碼。
對於一半來說,對於findsite(),您可以簡單地設置一個HashMap以使您從站點標識符到站點。 另一種清除方式是簡單地返回站點字符串,因此:
String findsite(txt) {
...................
if line.indexOf("site1-identifier")
return site1;
if(line.indexOf("site2-identifier")
return site2;
if(line.indexOf("site3-identifier")
return site3;
...
}
以這種方式使用indexOf()並不真正具有表達力; 我會使用equals()或contains()。
假設您的代碼效率低下。
實際解析輸入是否需要比(例如)1%的時間更多的時間?
如果沒有,您將擁有更大的“炸魚”。
我會更改findsite的類型以返回站點類型(超類),然后利用多態性...這應該比字符串操作要快...
您需要單獨的詞法分析器嗎?
使用地圖將站點配置為加載策略結構。 然后,需要基於“站點”進行簡單查找,然后執行適當的策略。 可以對findSite()執行相同的操作。
可以有一個標識符與站點的映射,然后僅對映射條目進行迭代。
// define this as a static somewhere ... build from a properties file
Map<String,String> m = new HashMap<String,String>(){{
put("site1-identifier","site2");
put("site2-identifier","site2");
}}
// in your method
for(Map.Entry<String,String> entry : m.entries()){
if( line.contains(entry.getKey())){
return line.getValue();
}
}
清潔工:是的,更快:不知道...應該足夠快
您可以使用反射
char site = line.charAt(4);
Method lexerMethod = this.getClass().getMethod( "loadLexer" + site, *parameters types here*)
Method parserMethod = this.getClass().getMethod( "loadparser" + site, *parameters types here*)
lexerMethod.invoke(this, *parameters here*);
parserMethod.invoke(this, *parameters here*);
我不了解Java,但是有些語言允許switch接受字符串。
switch(site)
{
case "site1": loadlexer1; loadparser1; break;
case "site2": loadlexer2; loadparser2; break;
...
}
至於秒位,請使用正則表達式提取標識符並打開。 使用enum
可能會更好。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.