[英]Does equality test order affect performance in Java?
我通常會發現自己在編寫這樣的代碼:
private List<Foo> fooList = new ArrayList<Foo>();
public Foo findFoo(FooAttr attr) {
for(Foo foo : fooList) {
if (foo.getAttr().equals(attr)) {
return foo;
}
}
}
但是,假設我正確地防止了空輸入,我還可以這樣表達循環:
for(Foo foo : fooList) {
if (attr.equals(foo.getAttr()) {
return foo;
}
}
我想知道上面的一種形式是否比另一種形式具有性能優勢。 我很清楚過早優化的危險,但是在這種情況下,我認為代碼無論哪種方式都清晰易讀,因此我正在尋找一個偏愛一種形式而不是另一種形式的理由,以便養成自己的編碼習慣,贊成那種形式。 我認為,如果列表足夠大,那么即使是很小的性能優勢也可能會花費大量時間。
特別是,我想知道第二種形式是否會更高效,因為equals()
方法是在同一對象而不是不同對象上重復調用的? 也許分支預測是一個因素?
我會在這里提供2條建議:
我認為考慮分支預測會擔心效率太低。 但是,我發現代碼的第二個示例更具可讀性,因為您將一致對象放在第一位。 同樣,如果你比較this
給一些其他的對象that
,我會把this
第一。
當然,equals由程序員定義,因此它可能是不對稱的。 您應該使等價關系成為現實,所以情況並非如此。 即使您具有等價關系,順序也可能很重要。 假設attr
是各種foo.getAttr
的超類,並且equals
方法的第一個測試將檢查另一個對象是否是同一類的實例。 然后attr.equals(foo.getAttr())
將通過第一次檢查,但是foo.getAttr().equals(attr)
將通過第一次檢查。
但是,很少擔心在此級別上具有效率。
這取決於equals方法的實現。 在這種情況下,我假設兩個對象都是同一類的實例。 因此,這意味着方法是平等的。 這沒有任何性能差異 。
如果兩個對象屬於同一類型,則它們應執行相同的操作。 如果不是這樣,那么您將無法真正預先知道會發生什么,但是通常它會很快停止(使用instanceof或其他方法)。
對於我自己,我通常以對給定參數進行非空檢查來啟動該方法,然后使用attr.equals(foo.getAttr())
因為在循環中不必檢查是否為空。 我猜只是一個偏愛的問題。
唯一會影響性能的是什么都不做的代碼。
在某些情況下,您所使用的代碼幾乎相同或相差如此之小,以至於無所謂。 就是這種情況。
交換.equals()有用的地方是,當您擁有一個已知類型的已知值且該值不能為null
(此處似乎不是這種情況)時。
例如
Object o = (Integer) 123;
String s = "Hello";
o.equals(s); // the type of equals is unknown and a virtual table look might be required
s.equals(o); // the type of equals is known and the class is final.
差別是如此之小,我不會擔心。
DEVENTER(n)很難做出決定,因為它很少依賴該決定,例如在公園中漫步的方式
-道格拉斯·亞當斯(Douglas Adams)和約翰·勞埃德(John Lloyd)的《里夫(Liff)》的深層含義。
性能應該是相同的,但就安全性而言,通常最好讓左操作數為您確定不為null的值,並讓equals方法處理null值。
舉個例子:
String s1 = null;
s1.equals("abc");
"abc".equals(s1);
兩次調用equals不相等,因為一個調用將發出NullPointerException(第一個),另一個將返回false。
正是由於這個原因,通常優選使用后一種形式與字符串常量進行比較。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.