1回顶部 尾递归转换能加快应用程序的速度,但不是所有的 JVM 都会做这种转换 很多算法用尾递归方法表示会显得格外简明。编译器会自动把这种方法转换成循环,以提高程序的性能。但在 Java 语言规范中,并没有要求一定要作这种转换,因此,并不是所有的 Java 虚拟机(JVM)都会做这种转换。这就意味着在 Java 语言中采用尾递归表示可能导致巨大的内存占用,而这并不是我们期望的结果。Eric Allen 在本文中阐述了动态编译将会保持语言的语义,而静态编译则通常不会。他说明了为什么这是一个重要问题,并提供了一段代码来帮助判断您的即时(JIT)编译器是否会在保持语言语义的同时做尾递归代码转换。 尾递归及其转换 相当多的程序包含有循环,这些循环运行的时间占了程序总运行时间的很大一部分。这些循环经常要反复更新不止一个变量,而每个变量的更新又经常依赖于其它变量的值。 如果把迭代看成是尾递归函数,那么,就可以把这些变量看成是函数的参数。简单提醒一下:如果一个调用的返回值被作为调用函数的值立即返回,那么,这个递归调用就是尾递归;尾递归不必记住调用时调用函数的上下文。 import java.util.Iterator; 注意 product 方法中的错误。product 方法通过把 accumulator 赋值为 0 调用 productHelp。它的值应为 1。否则,在类 Example 的任何实例上调用 product 都将产生 0 值,不管 Iterator 是什么值。 import java.util.*; 类 Example2 中的被覆盖的 productHelp 方法试图通过当 accumulator 小于“1”时抛出运行时异常来捕捉对 productHelp 的不正确调用。不幸的是,这样做将引入一个新的错误。如果 Iterator 含有任何 0 值的实例,都将使 productHelp 在自身的递归调用上崩溃。 int productHelp(Iterator i, int accumulator) { 于是,最初对 productHelp 的调用,结果成了对超类的方法的调用。超方法将通过简单地在 iterator 上循环来计算其结果。不会抛出任何异常。 2回顶部 您的 JIT 会做这种转换吗? 因此,如清单 3 中的示例所示,我们不能期望静态编译器会在保持语言语义的同时对 Java 代码执行尾递归转换。相反地,我们必须依靠 JIT 进行的动态编译。JIT 会不会做这种转换是取决于 JVM。 public class TailRecursionTest { 我们来考虑一下这个类的 loop 方法。这个方法只是尽可能长时间地对自身作递归调用。因为它永远不会返回,也不会以任何方式影响任何外部变量,因此如清单 5 所示替换其代码正文将保留程序的语义。 public class TailRecursionTest { 而且,事实上这也就是足够完善的编译器所做的转换。 记住:我们不能寄希望于我们的代码会总是运行在会转换尾递归调用的 JVM 上。因此,为了保证您的程序在所有 JVM 上都有适当的性能,您应始终努力把那些最自然地符合尾递归模式的代码按迭代风格编写。 学习的过程就是学会学习方法的过程,难道不是吗? |
闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾惧綊鏌熼梻瀵割槮缁炬儳缍婇弻鐔兼⒒鐎靛壊妲紒鐐劤缂嶅﹪寮婚悢鍏尖拻閻庨潧澹婂Σ顔剧磼閻愵剙鍔ゆ繝鈧柆宥呯劦妞ゆ帒鍊归崵鈧柣搴㈠嚬閸欏啫鐣峰畷鍥ь棜閻庯絻鍔嬪Ч妤呮⒑閸︻厼鍔嬮柛銊ョ秺瀹曟劙鎮欏顔藉瘜闂侀潧鐗嗗Λ妤呭锤婵犲洦鐓曢悗锝庡亝鐏忕増绻涢懝閭﹀殭闁宠鍨归埀顒婄秵閸嬧偓闁归攱妞藉缁樼瑹閸パ傜敖闂佺ǹ顑嗛惄顖炲箠閻旂⒈鏁嶆繛鎴炵懄閻濈兘姊洪崷顓℃闁哥姵顨婇幃鈥斥槈閵忊€斥偓鍫曟煟閹邦厼绲婚柍閿嬫閺屾洟宕卞Ο鐑樿癁闂佸搫鑻粔鐑铰ㄦ笟鈧弻娑㈠箻閸楃偛顬嬬紓浣戒含閸嬨倕鐣烽崡鐐╂婵☆垳銆嬬槐閬嶆⒒娴e憡鍟炲〒姘殜瀹曘垺銈i崘銊﹁緢闂佹寧妫冮弫顕€宕戦幘璇茬濠㈣泛锕f竟鏇㈡⒒娴e憡鍟炴繛璇х畵瀹曟粌鈽夐姀鐘插亶闂佸綊妫块悞锕傚磹閻㈠憡鐓曢煫鍥ㄦ惄濡茬ǹ霉濠婂牏鐣烘慨濠冩そ閺屽懘鎮欓懠璺侯伃婵犫拃鍐惧殶闁逞屽墲椤煤閹达箑纭€闁告劕妯婇崵鏇灻归悩宸剾闁轰礁娲︾换婵婎槼闁稿氦娅曠粋宥夊箚椤€崇秺閺佹劙宕堕埞搴撳亾婵犲啩绻嗛柟缁樺笧婢ф稑菐閸パ嶈含妞ゃ垺绋戦~婵嬵敆娴e洠鏅犲铏圭磼濮楀棙鐣烽悗鍏夊亾缂佸顑欏ḿ鏍ㄧ箾瀹割喕绨荤€瑰憡绻傞埞鎴︽偐閹绘巻鍋撻幖渚婄稏閹兼番鍔嶉埛鎴犵磼鐎n偒鍎ラ柛搴㈠姍閺岀喖宕ㄦ繝鍕啓濡炪倧绲块崑鎾舵崲濠靛顫呴柨婵嗘閵嗘劕顪冮妶鍡楃仴閻庢凹鍣i獮鎴﹀閵堝懎鑰垮┑鐐村灦閻熝囧储娴犲鈷戦悷娆忓缁舵煡鏌涘锝呬壕缂傚倷闄嶉崝宀勨€﹂悜钘夎摕鐎广儱鐗滃銊╂⒑閸涘﹥灏扮€光偓缁嬭法鏆︾憸鐗堝笒閸ㄥ倹銇勯弮鍌氫壕婵炲牓绠栧娲传閸曨剙绐涢梺鍝ュУ閹告儳顕h閸┾偓妞ゆ巻鍋撻柍瑙勫灴椤㈡瑩寮妶鍕繑闂備礁鎲¢幐濠氭儎椤栫偑鈧礁鈻庨幘鍐茶€垮┑鐐村灦閻熴垽骞忓ú顏呯厽闁绘ê鍘栭懜顏堟煕閺傝儻瀚伴柍璇茬Ч楠炲洭鎮ч崼銏犲箥闂備礁鎲¢崹顖炲磹閺嶎偀鍋撳鐐 (0) +1 闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾惧綊鏌熼梻瀵割槮缁炬儳缍婇弻鐔兼⒒鐎靛壊妲紒鐐劤濠€閬嶅焵椤掑倹鍤€閻庢凹鍙冨畷宕囧鐎c劋姹楅梺鍦劋閸ㄥ綊宕愰悙鐑樺仭婵犲﹤鍟扮粻鑽も偓娈垮枟婵炲﹪寮崘顔肩<婵炴垶鑹鹃獮鍫熶繆閻愵亜鈧倝宕㈡禒瀣瀭闁割煈鍋嗛々鍙夌節闂堟侗鍎愰柣鎾存礃缁绘盯宕卞Δ鍐唺缂備胶濮垫繛濠囧蓟瀹ュ牜妾ㄩ梺鍛婃尰閻熝呭垝鐠囧樊鍚嬪璺猴功閿涚喖姊绘笟鍥у缂佸顕划濠氼敍閻愭潙鈧敻鏌ㄥ┑鍡涱€楅柡瀣洴閹嘲鈻庡▎鎴犳殼闂佽鍠楅〃濠囧极閹邦厽鍎熼柍鈺佸暟娴滃爼姊绘担铏瑰笡闁规瓕顕х叅闁绘梻鍘ч拑鐔衡偓骞垮劚椤︻垶鎮″☉妯忓綊鏁愰崨顔兼殘闂佽绻戦幐鎼佸煘閹达附鍊烽柤纰卞墮椤e爼姊洪幖鐐插缂傚秴锕ら敃銏℃媴閾忓湱锛滅紓鍌欓檷閸ㄧ懓顕i鈧弻锟犲焵椤掍焦缍囬柍瑙勫劤娴滅偓鎱ㄥΟ鐓庝壕閻庢熬鎷� (0) +1 闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾惧綊鏌熼梻瀵割槮缁炬儳缍婇弻鐔兼⒒鐎靛壊妲紒鐐劤缂嶅﹪寮婚悢鍏尖拻閻庨潧澹婂Σ顔剧磼閻愵剙鍔ょ紓宥咃躬瀵鎮㈤崗灏栨嫽闁诲酣娼ф竟濠偽i鍓х<闁绘劦鍓欓崝銈囩磽瀹ュ拑韬€殿喖顭烽幃銏ゅ礂鐏忔牗瀚介梻浣告贡閾忓酣宕板Δ鍜佹晛闁哄稁鍘介埛鎴犵磼鐎n偒鍎ラ柛搴㈠姍閺屾盯濡搁妷锕€浠村Δ鐘靛仜閸燁偉鐏冮梺閫炲苯澧撮柛鈹垮劜瀵板嫭绻涢悙顒傗偓濠氭煟鎼搭垳绉甸柛鎾寸〒缁絽螖娴i绠氶梺缁樺姦娴滄粓鍩€椤掍礁濮嶇€殿喗褰冮オ浼村醇閻旇渹绨甸梻浣芥硶閸犳挻鎱ㄩ幘顔藉珔闁绘柨鍚嬮悡銉︾節闂堟稒锛嶆俊鎻掓憸缁辨帡鎮崨顖溞滈梺鍝勮閸斿矂鍩為幋锕€骞㈡慨妤€鐗忕粈濠冪節绾版ɑ顫婇柛瀣閳ь剚鍑归崰姘i幇鏉跨閻庢稒锚椤庢捇姊洪崨濠勭畵閻庢氨鍏橀崺鈧い鎺嗗亾闁活厼鍊垮璇测槈閵忕姈鈺呮煏婢诡垰鍟伴崢浠嬫煟鎼淬埄鍟忛柛鐘崇墵閳ワ箓鏌ㄧ€b晝绠氶梺褰掓?缁€渚€鎮″☉銏$厱閻忕偛澧介悡顖滅磼閵娿倗鐭欐慨濠勭帛閹峰懘宕ㄩ棃娑氱Ш鐎殿喚鏁婚、妤呭磼濠婂懐鍘梻浣侯攰閹活亞鈧潧鐭傚顐﹀磼閻愬鍙嗛梺缁樻礀閸婂湱鈧熬鎷� (0) +1
闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾惧綊鏌熼梻瀵割槮缁炬儳缍婇弻鐔兼⒒鐎靛壊妲紒鐐劤缂嶅﹪寮婚悢鍏尖拻閻庨潧澹婂Σ顔剧磼閻愵剙鍔ゆ繝鈧柆宥呯劦妞ゆ帒鍊归崵鈧柣搴㈠嚬閸欏啫鐣峰畷鍥ь棜閻庯絻鍔嬪Ч妤呮⒑閸︻厼鍔嬮柛銊ョ秺瀹曟劙鎮欏顔藉瘜闂侀潧鐗嗗Λ妤呭锤婵犲洦鐓曢悗锝庡亝鐏忕増绻涢懝閭﹀殭闁宠鍨归埀顒婄秵閸嬧偓闁归攱妞藉缁樼瑹閸パ傜敖闂佺ǹ顑嗛惄顖炲箠閻旂⒈鏁嶆繛鎴炵懄閻濈兘姊洪崷顓℃闁哥姵顨婇幃鈥斥槈閵忊€斥偓鍫曟煟閹邦厼绲婚柍閿嬫閺屾洟宕卞Ο鐑樿癁闂佸搫鑻粔鐑铰ㄦ笟鈧弻娑㈠箻閸楃偛顬嬬紓浣戒含閸嬨倕鐣烽崡鐐╂婵☆垳銆嬬槐閬嶆⒒娴e憡鍟炲〒姘殜瀹曘垺銈i崘銊﹁緢闂佹寧妫冮弫顕€宕戦幘璇茬濠㈣泛锕f竟鏇㈡⒒娴e憡鍟炴繛璇х畵瀹曟粌鈽夐姀鐘插亶闂佸綊妫块悞锕傚磹閻㈠憡鐓曢煫鍥ㄦ惄濡茬ǹ霉濠婂牏鐣烘慨濠冩そ閺屽懘鎮欓懠璺侯伃婵犫拃鍐惧殶闁逞屽墲椤煤閹达箑纭€闁告劕妯婇崵鏇灻归悩宸剾闁轰礁娲︾换婵婎槼闁稿氦娅曠粋宥夊箚椤€崇秺閺佹劙宕堕埞搴撳亾婵犲啩绻嗛柟缁樺笧婢ф稑菐閸パ嶈含妞ゃ垺绋戦~婵嬵敆娴e洠鏅犲铏圭磼濮楀棙鐣烽悗鍏夊亾缂佸顑欏ḿ鏍ㄧ箾瀹割喕绨荤€瑰憡绻傞埞鎴︽偐閹绘巻鍋撻幖渚婄稏閹兼番鍔嶉埛鎴犵磼鐎n偒鍎ラ柛搴㈠姍閺岀喖宕ㄦ繝鍕啓濡炪倧绲块崑鎾舵崲濠靛顫呴柨婵嗘閵嗘劕顪冮妶鍡楃仴閻庢凹鍣i獮鎴﹀閵堝懎鑰垮┑鐐村灦閻熝囧储娴犲鈷戦悷娆忓缁舵煡鏌涘锝呬壕缂傚倷闄嶉崝宀勨€﹂悜钘夎摕鐎广儱鐗滃銊╂⒑閸涘﹥灏扮€光偓缁嬭法鏆︾憸鐗堝笒閸ㄥ倹銇勯弮鍌氫壕婵炲牓绠栧娲传閸曨剙鍋嶉梺鎼炲妼缂嶅﹪骞忛幋锔藉亜闁稿繗鍋愰崢顏呯節閵忥絾纭鹃柣妤€妫濆畷婵嗩潩閼哥數鍘介柟鍏兼儗閸犳牕顕i鑺ュ弿濠电姴鎳忛鐘电磼椤旇姤顥堢€规洖宕灃闁逞屽墴椤㈡梻鈧稒岣跨粻楣冩煕椤愩倕鏋戞い銉ョ墦閺屸€崇暆鐎n剛鏆ら悗瑙勬礃閿曘垽銆侀弮鍫濈妞ゆ帒鍊烽柇顖炴⒒閸屾瑧顦﹂柟纰卞亰閹本寰勫畝鈧粈濠偯归敐鍛棌闁搞倖娲橀妵鍕即濡も偓娴滈箖鎮楃憴鍕闁绘牕鍚嬫穱濠囨倻閽樺娼婇梺缁樏畷顒勊夊鑸碘拻濞撴埃鍋撻柍褜鍓涢崑娑㈡嚐椤栨稒娅犻柟缁㈠枟閻撴盯鎮橀悙鎻掆挃闁靛棙甯¢弻宥堫檨闁告挶鍔庣槐鐐哄幢濞戞ḿ锛涢梺鍛婁緱閸垶鎮炴繝鍐︿簻闁规儳宕悘顏堟煟閹惧啿鏆i柡宀嬬畱铻e〒姘煎灡閳绘挸鈹戦垾鍐茬骇闁诡喖鍊垮璇差吋閸ャ劌鐝伴梺鑲┾拡閸庣柉顦抽柕鍥у婵偓闁愁厼绻愮紞濠呮闁哄鐗冮弲婵堝婵傚憡鐓忓┑鐐茬仢閸旀﹢鏌涚€c劌鐏查柡灞糕偓宕囨殕闁逞屽墴瀹曚即骞囬鍓х暥闂佺粯姊婚崢褔宕归崒娑栦簻闁哄啫鍊甸幏鈩冪箾閻撳酣鍙勯柡宀嬬稻閹棃濡舵惔銏㈢Х婵犵數鍋涘鍫曟晝閵忕姷鏆﹂柡鍥╁枔闂勫嫰鏌℃径濠冾棞婵炲樊鍙冮妴浣割潩鐠鸿櫣鍔﹀銈嗗笒鐎氼剟鎷戦悢鍏肩叆闁绘柨鎼瓭闂佺粯甯掗悘姘跺Φ閸曨垰绠抽柟瀛樼箥娴犻箖姊洪幖鐐测偓鏇犵矓瑜版帒钃熼柡鍥╁枎缁剁偞绻涢幋鐐跺妞ゆ洝浜槐鎾存媴闂堟稑顬堝銈庡幖閸㈡煡锝炶箛鎾佹椽顢旈崟顏嗙倞闂備礁鎲″ú锕傚礈濞嗘垹鐜绘繛鎴欏灪閳锋垹绱掔€n偒鍎ラ柛搴㈠灴閺屾稓鈧絻鍔岄埀顒佺☉铻為柕蹇嬪€栭埛鎴犵磽娴e顏呮叏婢舵劖鐓曢幖瀛樼☉閳ь剚绻傞悾鐑藉箛閺夊灝鐎銈嗗姧缁茶棄顕i崹顔规斀闁宠棄妫楅悘锝夋煕濡姴瀚々鎻捨旈敐鍛殲闁稿﹤鐏氶幈銊ノ熼悡搴濆闁诲孩鐔幏锟�闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾惧綊鏌熼梻瀵割槮缁炬儳缍婇弻鐔兼⒒鐎靛壊妲紒鐐劤缂嶅﹪寮婚悢鍏尖拻閻庨潧澹婂Σ顔剧磼閹冣挃闁硅櫕鎹囬垾鏃堝礃椤忎礁浜鹃柨婵嗙凹缁ㄥジ鏌熼惂鍝ョМ闁哄矉缍侀、姗€鎮欓幖顓燁棧闂備線娼уΛ娆戞暜閹烘缍栨繝闈涱儐閺呮煡鏌涘☉鍗炲妞ゃ儲鑹鹃埞鎴炲箠闁稿﹥顨嗛幈銊╂倻閽樺锛涢梺缁樺姉閸庛倝宕戠€n喗鐓熸俊顖濆吹濠€浠嬫煃瑜滈崗娑氭濮橆剦鍤曢柟缁㈠枛椤懘鏌eΟ鑽ゅ灩闁搞儯鍔庨崢閬嶆⒑閺傘儲娅呴柛鐔村妽缁傛帡鏁傞崜褏锛滃銈嗘⒒閹虫挻鏅堕幓鎹涘酣宕惰闊剟鏌熼鐣屾噰妞ゃ垺妫冨畷鐔煎Ω閵夈倕顥氶梻浣告惈缁嬩線宕㈤懖鈺冪焼濠㈣泛鏈崰鎰扮叓閸ャ劍绀€闁搞劍绻傞埞鎴︽偐鐎圭姴顥濈紓浣哄缂嶄線寮婚敐鍛傜喖鎮滃Ο閿嬬亞婵犵妲呴崑鍛垝閹炬剚娼栭柧蹇撴贡閻捇鏌涢埄鍐炬當妞ゅ繐鐡ㄧ换娑㈠醇閻斿摜顦伴梺鍝勭焿缂嶄線鐛Ο灏栧亾濞戞瑡缂氭い锔垮嵆濮婃椽宕崟顓犱紘闂佸摜濮甸悧鐘差嚕婵犳艾鐐婃い鎺嶇劍濞呭洭姊洪柅鐐茶嫰婢ф挳鏌熼鏂よ€块柡灞芥椤撳ジ宕卞▎蹇撶疄闂傚倷绶氬ḿ褔鎮ч崱娑樼閻庯綆鍠栫壕鍧楁煛閸愩劎澧涢柣鎾寸洴閹﹢鎮欐0婵嗘闂侀€炲苯澧紒璇插€块、姘舵晲婢跺﹪鍞堕梺鍝勬川閸嬬喖顢欓崶顒佺厵闁兼祴鏅炶棢闂侀€炲苯澧€殿喛娉涜灒濠电姴娲﹂埛鎺楁煕鐏炲墽鎳呮い锔肩畵閺岀喓鍠婇崡鐐板枈閻庢鍠氶弫濠氥€佸Δ鍛<婵犲﹤鎳愰崢顖炴⒒娴d警鏀伴柟娲讳簽缁骞嬮敂钘変簵闂佺偨鍎查崜姘舵偄閸℃稒鍋i柛婵嗗婵炲洭鏌涢鐘插姎闁告垹濞€楠炴牕菐椤掆偓婵′粙鏌i幘瀵告噰婵﹥妞介、姗€濡歌閺嗙娀姊洪崫鍕靛剭闁稿﹥绻堝璇差吋閸ャ劌鐝伴梺鑲┾拡閸撴盯顢欐繝鍕=濞达絼绮欓崫娲煙閻熺増鎼愰柣锝囧厴楠炴帡骞嬮鐔峰厞婵$偑鍊栭崹鐓幬涢崟顒傤洸闁诡垎灞惧瘜闁诲函缍嗘禍婊堫敆閵忕姭鏀芥い鏍ㄥ搸閸嬨垽鏌″畝瀣?濞寸媴濡囬幏鐘诲箵閹烘埈娼涢梻鍌欑劍閻綊宕愬┑鍫笉闁哄稁鍘奸拑鐔兼煥濠靛棙鍟掗柣鏂跨殱閺嬪酣鏌熼鍡楀閸炴煡姊婚崒娆愮グ婵☆偄瀚板畷顖涘閺夋垹鐛ラ梺鍝勭▉閸樺ジ鎷戦悢鍏肩叆婵犻潧妫Σ鍝ョ磼椤愩垻效闁哄本绋撴禒锔剧磼閵忥紕鏆﹂梺璇插绾板秹鎯勯姘兼綎闁绘垶蓱婵粓鏌熷▓鍨珮婵″樊鍠氱槐鎾存媴閸撳弶楔闂佽桨鐒﹂幃鍌炵嵁閹达箑顫呴柣姗嗗亝閺傗偓闂備焦鎮堕崕顕€寮插┑瀣剨闁割偁鍎查埛鎴犵磼鐎n偄顕滄繝鈧幍顔炬/闁哄娉曟晥闂佽鍠楅敃銏ょ嵁濡偐纾兼俊顖炴敱鐎氬ジ姊绘担鍛婂暈缂佽鍊婚埀顒佸嚬閸欏啴寮鍜佸悑濠㈣泛顑囬崢鍗炩攽閳藉棗鐏″ù婊€绮欏畷鎴﹀閵堝棛鍘撻梺闈涱檧闂勫嫰藟閸懇鍋撶憴鍕闁挎洏鍨介妴浣糕枎閹惧啿绨ユ繝銏n嚃閸ㄦ澘煤閿曞倹鍋傞柡鍥ュ灪閻撴瑩鏌熸担鍐╃彧婵炲懎鎳庨埞鎴︽晬閸曨偄浠橀梺瀹狀潐閸ㄥ潡銆佸▎鎾崇畾鐟滃秹鐛€n亖鏀芥い鏃傘€嬮弨缁樹繆閻愭壆鐭欐鐐插暣閹粓鎸婃径宀勭崜闂備礁婀辨灙閻庡灚甯″畷顒勫Ω閳哄倵鎷绘繛杈剧悼閸庛倝宕甸埀顒勬⒑閹肩偛鈧牠鎮ч悩鑽ゅ祦闊洦绋掗弲鎼佹煥閻曞倹瀚�>>
正在阅读:提高 Java 代码的性能提高 Java 代码的性能
2005-08-15 14:40
出处:
责任编辑:xietaoming