中文字幕日韩精品一区二区免费_精品一区二区三区国产精品无卡在_国精品无码专区一区二区三区_国产αv三级中文在线

Java代碼的優(yōu)化方法-創(chuàng)新互聯(lián)

如何優(yōu)化java代碼?相信很多新手小白對代碼優(yōu)化的了解處于懵懂狀態(tài),小編給你幾點建議,通過幾點建議,希望你能收獲更多。如下資料是關(guān)于Java代碼優(yōu)化方法的內(nèi)容。

成都創(chuàng)新互聯(lián)長期為千余家客戶提供的網(wǎng)站建設(shè)服務(wù),團隊從業(yè)經(jīng)驗10年,關(guān)注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為深州企業(yè)提供專業(yè)的成都做網(wǎng)站、成都網(wǎng)站設(shè)計,深州網(wǎng)站改版等技術(shù)服務(wù)。擁有十載豐富建站經(jīng)驗和眾多成功案例,為您定制開發(fā)。

1 .只做有目的性的優(yōu)化

大型軟件系統(tǒng)肯定非常關(guān)注性能問題。雖然我們希望能夠?qū)懗鲎罡咝У拇a,但很多時候,如果想對代碼進行優(yōu)化,我們卻無從下手。例如,下面的這段代碼會影響到性能嗎?
public void processIntegers(List<Integer> integers) {

for (Integer value: integers) {
   for (int i = integers.size() - 1; i >= 0; i--) {
     value += integers.get(i);
   }
}

}
這就得視情況而定了。上面這段代碼可以看出它的處理算法是O(n3)(使用 大O符號 ),其中n是list集合的大小。如果n只有5,那么就不會有問題,只會執(zhí)行25次迭代。但如果n是10萬,那可能會影響性能了。請注意,即使這樣我們也不能判定肯定會有問題。盡管此方法需要執(zhí)行10億次邏輯迭代,但會不會對性能產(chǎn)生影響仍然有待討論。

例如,假設(shè)客戶端是在它自己的線程中執(zhí)行這段代碼,并且異步等待計算完成,那么它的執(zhí)行時間有可能是可以接受的。同樣,如果系統(tǒng)部署在了生產(chǎn)環(huán)境上,但是沒有客戶端進行調(diào)用,那我們根本沒必要去對這段代碼進行優(yōu)化,因為壓根就不會消耗系統(tǒng)的整體性能。事實上,優(yōu)化性能以后系統(tǒng)會變得更加復(fù)雜,悲劇的是系統(tǒng)的性能卻沒有因此而提高。

最重要的是天下沒有免費的午餐,因此為了降低代價,我們通常會通過類似于緩存、循環(huán)展開或預(yù)計算值這類技術(shù)去實現(xiàn)優(yōu)化,這樣反而增加了系統(tǒng)的復(fù)雜性,也降低了代碼的可讀性。如果這種優(yōu)化可以提高系統(tǒng)的性能,那么即使變得復(fù)雜,那也是值得的,但是做決定之前,必須首先知道這兩條信息:

性能要求是什么
性能瓶頸在哪里
首先我們需要清楚地知道性能要求是什么。如果最終是在要求以內(nèi),并且最終用戶也沒有提出什么異議,那么就沒有必要進行性能優(yōu)化。但是,當(dāng)添加了新功能或者系統(tǒng)的數(shù)據(jù)量達(dá)到一定規(guī)模以后就必須進行優(yōu)化了,否則可能會出現(xiàn)問題。

在這種情況下,不應(yīng)該靠直覺,也不應(yīng)該依靠檢查。因為即使是像Martin Fowler這樣有經(jīng)驗的開發(fā)人員也容易做一些錯誤的優(yōu)化,正如在 重構(gòu) (第70頁)一文中解釋的那樣:

引用

如果分析了足夠多的程序以后,你會發(fā)現(xiàn)關(guān)于性能的有趣之處在于,大部分時間都浪費在了系統(tǒng)中的一小部分代碼中里面。如果對所有代碼進行了同樣的優(yōu)化,那么最終結(jié)果就是浪費了90%的優(yōu)化,因為優(yōu)化過以后的代碼運行得頻率并不多。因為沒有目標(biāo)而做的優(yōu)化所耗費的時間,都是在浪費時間。

作為一名身經(jīng)百戰(zhàn)的開發(fā)人員,我們應(yīng)該認(rèn)真對待這一觀點。第一次猜測不僅沒有提高系統(tǒng)的性能,而且90%的開發(fā)時間完全是浪費了。相反,我們應(yīng)該在生產(chǎn)環(huán)境(或者預(yù)生產(chǎn)環(huán)境中)執(zhí)行常見用例,并找出在執(zhí)行過程中是哪部分在消耗系統(tǒng)資源,然后對系統(tǒng)進行 配置 。例如消耗大部分資源的代碼只占了10%,那么優(yōu)化其余90%的代碼就是浪費時間。

根據(jù)分析結(jié)果,要想使用這些知識,我們應(yīng)該從最常見的情況入手。因為這將確保實際付出的努力最終是可以提高系統(tǒng)的性能。每次優(yōu)化后,都應(yīng)該重復(fù)分析步驟。因為這不僅可以確保系統(tǒng)的性能真的得到了改善,也可以看出再對系統(tǒng)進行優(yōu)化后,性能瓶頸是在哪個部分(因為解決完一個瓶頸以后,其它瓶頸可能消耗系統(tǒng)更多的整體資源)。需要注意的是,在現(xiàn)有瓶頸中花費的時間百分比很可能會增加,因為剩下的瓶頸是暫時不變的,而且隨著目標(biāo)瓶頸的消除,整個執(zhí)行時間應(yīng)該會減少。

盡管在Java系統(tǒng)中想要對概要文件進行全面檢查需要很大的容量,但是還是有一些很常見的工具可以幫助發(fā)現(xiàn)系統(tǒng)的性能熱點,這些工具包括 JMeter 、 AppDynamics 和 YourKit 。另外,還可以參見DZone的 性能監(jiān)測指南 ,獲取更多關(guān)于Java程序性能優(yōu)化的信息。

雖然性能是許多大型軟件系統(tǒng)一個非常重要的組成部分,也成為產(chǎn)品交付管道中自動化測試套件的一部分,但是還是不能夠盲目的且沒有目的的進行優(yōu)化。相反,應(yīng)該對已經(jīng)掌握的性能瓶頸進行特定的優(yōu)化。這不僅可以幫助我們避免增加了系統(tǒng)的復(fù)雜性,而且還讓我們少走彎路,不去做那些浪費時間的優(yōu)化。

2.常量盡量使用枚舉

需要用戶列出一組預(yù)定義或常量值的場景有很多,例如在web應(yīng)用程序中可能遇到的HTTP響應(yīng)代碼。最常見的實現(xiàn)技術(shù)之一是新建類,該類里面有很多靜態(tài)的final類型的值,每個值都應(yīng)該有一句注釋,描述該值的含義是什么:

public class HttpResponseCodes {
public static final int OK = 200;
public static final int NOT_FOUND = 404;
public static final int FORBIDDEN = 403;
}
if (getHttpResponse().getStatusCode() == HttpResponseCodes.OK) {
// Do something if the response code is OK
}
能夠有這種思路就已經(jīng)非常好了,但這還是有一些缺點:

沒有對傳入的整數(shù)值進行嚴(yán)格的校驗
由于是基本數(shù)據(jù)類型,因此不能調(diào)用狀態(tài)代碼上的方法
在第一種情況下只是簡單的創(chuàng)建了一個特定的常量來表示特殊的整數(shù)值,但并沒有對方法或變量進行限制,因此使用的值可能會超出定義的范圍。例如:

public class HttpResponseHandler {
public static void printMessage(int statusCode) {
System.out.println("Recieved status of " + statusCode);
}
}
HttpResponseHandler.printMessage(15000);
盡管15000并不是有效的HTTP響應(yīng)代碼,但是由于服務(wù)器端也沒有限制客戶端必須提供有效的整數(shù)。在第二種情況下,我們沒有辦法為狀態(tài)代碼定義方法。例如,如果想要檢查給定的狀態(tài)代碼是否是一個成功的代碼,那就必須定義一個單獨的函數(shù):

public class HttpResponseCodes {
public static final int OK = 200;
public static final int NOT_FOUND = 404;
public static final int FORBIDDEN = 403;
public static boolean isSuccess(int statusCode) {
return statusCode >= 200 && statusCode < 300;
}
}
if (HttpResponseCodes.isSuccess(getHttpResponse().getStatusCode())) {
// Do something if the response code is a success code
}
為了解決這些問題,我們需要將常量類型從基本數(shù)據(jù)類型改為自定義類型,并只允許自定義類的特定對象。這正是 Java枚舉(enum) 的用途。使用enum,我們可以一次性解決這兩個問題:

public enum HttpResponseCodes {
OK(200),
FORBIDDEN(403),
NOT_FOUND(404);
private final int code;
HttpResponseCodes(int code) {
this.code = code;
}
public int getCode() {
return code;
}
public boolean isSuccess() {
return code >= 200 && code < 300;
}
}
if (getHttpResponse().getStatusCode().isSuccess()) {
// Do something if the response code is a success code
}
同樣,現(xiàn)在還可以要求在調(diào)用方法的時候提供必須有效的狀態(tài)代碼:

public class HttpResponseHandler {
public static void printMessage(HttpResponseCode statusCode) {
System.out.println("Recieved status of " + statusCode.getCode());
}
}
HttpResponseHandler.printMessage(HttpResponseCode.OK);
值得注意的是,舉這個例子事項說明如果是常量,則應(yīng)該盡量使用枚舉,但并不是說什么情況下都應(yīng)該使用枚舉。在某些情況下,可能希望使用一個常量來表示某個特殊值,但是也允許提供其它的值。例如,大家可能都知道圓周率,我們可以用一個常量來捕獲這個值(并重用它):

public class NumericConstants {
public static final double PI = 3.14;
public static final double UNIT_CIRCLE_AREA = PI PI;
}
public class Rug {
private final double area;
public class Run(double area) {
this.area = area;
}
public double getCost() {
return area
2;
}
}
// Create a carpet that is 4 feet in diameter (radius of 2 feet)
Rug fourFootRug = new Rug(2 * NumericConstants.UNIT_CIRCLE_AREA);
因此,使用枚舉的規(guī)則可以歸納為:

當(dāng)所有可能的離散值都已經(jīng)提前知道了,那么就可以使用枚舉

再拿上文中所提到的HTTP響應(yīng)代碼為例,我們可能知道HTTP狀態(tài)代碼的所有值(可以在RFC 7231中找的到,它定義了HTTP 1.1協(xié)議)。因此使用了枚舉。在計算圓周率的情況下,我們不知道關(guān)于圓周率的所有可能值(任何可能的double都是有效的),但同時又希望為圓形的rugs創(chuàng)建一個常量,使計算更容易(更容易閱讀);因此定義了一系列常量。

如果不能提前知道所有可能的值,但是又希望包含每個值的字段或方法,那么最簡單的方法就是可以新建一個類來表示數(shù)據(jù)。盡管沒有說過什么場景應(yīng)該絕對不用枚舉,但要想知道在什么地方、什么時間不使用枚舉的關(guān)鍵是提前意識到所有的值,并且禁止使用其他任何值。

3.重新定義類里面的equals()方法

對象識別可能是一個很難解決的問題:如果兩個對象在內(nèi)存中占據(jù)相同的位置,那么它們是相同的嗎?如果它們的id相同,它們是相同的嗎?或者如果所有的字段都相等呢?雖然每個類都有自己的標(biāo)識邏輯,但是在系統(tǒng)中有很多西方都需要去判斷是否相等。例如,有如下的一個類,表示訂單購買…

public class Purchase {
private long id;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
}
……就像下面寫的這樣,代碼中肯定有很多地方都是類似于的:

Purchase originalPurchase = new Purchase();
Purchase updatedPurchase = new Purchase();
if (originalPurchase.getId() == updatedPurchase.getId()) {
// Execute some logic for equal purchases
}
這些邏輯調(diào)用的越多(反過來,違背了 DRY原則 ),Purchase類的身份信息也會變得越來越多。如果出于某種原因,更改了Purchase類的身份邏輯(例如,更改了標(biāo)識符的類型),則需要更新標(biāo)識邏輯所在的位置肯定也非常多。

我們應(yīng)該在類的內(nèi)部初始化這個邏輯,而不是通過系統(tǒng)將Purchase類的身份邏輯進行過多的傳播。乍一看,我們可以創(chuàng)建一個新的方法,比如isSame,這個方法的入?yún)⑹且粋€Purchase對象,并對每個對象的id進行比較,看看它們是否相同:

public class Purchase {
private long id;
public boolean isSame(Purchase other) {
return getId() == other.gerId();  
}
}
雖然這是一個有效的解決方案,但是忽略了Java的內(nèi)置功能:使用equals方法。Java中的每個類都是繼承了Object類,雖然是隱式的,因此同樣也就繼承了equals方法。默認(rèn)情況下,此方法將檢查對象標(biāo)識(內(nèi)存中相同的對象),如JDK中的對象類定義(version 1.8.0_131)中的以下代碼片段所示:

public boolean equals(Object obj) {
return (this == obj);
}
這個equals方法充當(dāng)了注入身份邏輯的自然位置(通過覆蓋默認(rèn)的equals實現(xiàn)):

public class Purchase {
private long id;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;}
@Override
br/>@Override<br/public double getIntestRate() {
return 0.03;}
@Override
br/>@Override<br/public double getIntestRate() {
return 0.04;}
@Override
br/>@Override<br/public double getIntestRate() {
return 0.05;}
@Override<br/" rel="nofollow">br/>}
@Override<br/public boolean supportsDeposits() {
return false;
}
}
這不僅將每個帳戶特有的信息封裝到了到自己的類中,而且還支持用戶可以在兩種重要的方式中對設(shè)計進行變化。首先,如果想要添加一個新的銀行帳戶類型,只需創(chuàng)建一個新的具體類,實現(xiàn)了BankAccount的接口,給出兩個方法的具體實現(xiàn)就可以了。在條件結(jié)構(gòu)設(shè)計中,我們必須在枚舉中添加一個新值,在兩個方法中添加新的case語句,并在每個case語句下插入新帳戶的邏輯。

其次,如果我們希望在BankAccount接口中添加一個新方法,我們只需在每個具體類中添加新方法。在條件設(shè)計中,我們必須復(fù)制現(xiàn)有的switch語句并將其添加到我們的新方法中。此外,我們還必須在每個case語句中添加每個帳戶類型的邏輯。

在數(shù)學(xué)上,當(dāng)我們創(chuàng)建一個新方法或添加一個新類型時,我們必須在多態(tài)和條件設(shè)計中做出相同數(shù)量的邏輯更改。例如,如果我們在多態(tài)設(shè)計中添加一個新方法,我們必須將新方法添加到所有n個銀行帳戶的具體類中,而在條件設(shè)計中,我們必須在我們的新方法中添加n個新的case語句。如果我們在多態(tài)設(shè)計中添加一個新的account類型,我們必須在BankAccount接口中實現(xiàn)所有的m數(shù),而在條件設(shè)計中,我們必須向每個m現(xiàn)有方法添加一個新的case語句。

雖然我們必須做的改變的數(shù)量是相等的,但變化的性質(zhì)卻是完全不同的。在多態(tài)設(shè)計中,如果我們添加一個新的帳戶類型并且忘記包含一個方法,編譯器會拋出一個錯誤,因為我們沒有在我們的BankAccount接口中實現(xiàn)所有的方法。在條件設(shè)計中,沒有這樣的檢查,以確保每個類型都有一個case語句。如果添加了新類型,我們可以簡單地忘記更新每個switch語句。這個問題越嚴(yán)重,我們就越重復(fù)我們的switch語句。我們是人類,我們傾向于犯錯誤。因此,任何時候,只要我們可以依賴編譯器來提醒我們錯誤,我們就應(yīng)該這么做。

關(guān)于這兩種設(shè)計的第二個重要注意事項是它們在外部是等同的。例如,如果我們想要檢查一個支票帳戶的利率,條件設(shè)計就會類似如下:

BankAccount checkingAccount = new BankAccount(BankAccountType.CHECKING);
System.out.println(checkingAccount.getInterestRate()); // Output: 0.03
相反,多態(tài)設(shè)計將類似如下:

BankAccount checkingAccount = new CheckingAccount();
System.out.println(checkingAccount.getInterestRate()); // Output: 0.03
從外部的角度來看,我們只是在BankAccount對象上調(diào)用getintereUNK()。如果我們將創(chuàng)建過程抽象為一個工廠類的話,這將更加明顯:

public class ConditionalAccountFactory {
public static BankAccount createCheckingAccount() {
return new BankAccount(BankAccountType.CHECKING);
}
}
public class PolymorphicAccountFactory {
public static BankAccount createCheckingAccount() {
return new CheckingAccount();
}
}
// In both cases, we create the accounts using a factory
BankAccount conditionalCheckingAccount = ConditionalAccountFactory.createCheckingAccount();
BankAccount polymorphicCheckingAccount = PolymorphicAccountFactory.createCheckingAccount();
// In both cases, the call to obtain the interest rate is the same
System.out.println(conditionalCheckingAccount.getInterestRate()); // Output: 0.03
System.out.println(polymorphicCheckingAccount.getInterestRate()); // Output: 0.03
將條件邏輯替換成多態(tài)類是非常常見的,因此已經(jīng)發(fā)布了將條件語句重構(gòu)為多態(tài)類的方法。這里就有一個簡單的例子。此外, 馬丁·福勒(Martin Fowler)的《重構(gòu)》 (p . 255)也描述了執(zhí)行這個重構(gòu)的詳細(xì)過程。

以上就是Java代碼優(yōu)化方法的詳細(xì)內(nèi)容了,看完之后是否有所收獲呢?如果想了解更多相關(guān)內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊!

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機、免備案服務(wù)器”等云主機租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。

分享題目:Java代碼的優(yōu)化方法-創(chuàng)新互聯(lián)
標(biāo)題來源:http://www.rwnh.cn/article42/cecshc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站策劃響應(yīng)式網(wǎng)站、網(wǎng)站設(shè)計網(wǎng)站設(shè)計公司、網(wǎng)站導(dǎo)航面包屑導(dǎo)航

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)公司
昌黎县| 景洪市| 神农架林区| 隆安县| 沾化县| 莲花县| 科技| 耒阳市| 永嘉县| 丰顺县| 台东市| 余干县| 宁波市| 措勤县| 马公市| 合山市| 贵德县| 兰州市| 博湖县| 华亭县| 永济市| 同德县| 奉化市| 揭阳市| 乐陵市| 安宁市| 东山县| 漾濞| 锡林郭勒盟| 诸暨市| 漳州市| 宁陕县| 溧水县| 宝坻区| 廊坊市| 锦州市| 诸城市| 临邑县| 湄潭县| 兴城市| 安义县|