[解決済み】if (a - b < 0)とif (a < b)の違いについて)
質問
Java の
ArrayList
のソースコードで、ifステートメントでいくつかの比較に気づきました。
Java 7 では、メソッド
grow(int)
が使用します。
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
Java 6の場合。
grow
は存在しなかった。メソッド
ensureCapacity(int)
を使用します。
if (newCapacity < minCapacity)
newCapacity = minCapacity;
変更の理由は何だったのでしょうか?パフォーマンスの問題なのか、それとも単なるスタイルなのか?
ゼロと比較した方が速いのは想像がつきますが、マイナスかどうかをチェックするためだけに完全な引き算をするのは、ちょっとやりすぎな気がします。また、バイトコードの面でも、これは2つの命令(
ISUB
と
IF_ICMPGE
)ではなく、1つ(
IFGE
).
解決方法は?
a < b
と
a - b < 0
は、2つの異なる意味を持つことがあります。次のようなコードを考えてみましょう。
int a = Integer.MAX_VALUE;
int b = Integer.MIN_VALUE;
if (a < b) {
System.out.println("a < b");
}
if (a - b < 0) {
System.out.println("a - b < 0");
}
実行すると、次のように表示されます。
a - b < 0
. 何が起こるかというと
a < b
は明らかに誤りですが
a - b
がオーバーフローして
-1
であり、負である。
さて,ここで,配列の長さが本当に
Integer.MAX_VALUE
. のコードは
ArrayList
はこのようになります。
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
oldCapacity
は本当に近い
Integer.MAX_VALUE
だから
newCapacity
(これは
oldCapacity + 0.5 * oldCapacity
がオーバーフローして
Integer.MIN_VALUE
(つまりマイナス)です。では、引き算の
minCapacity
アンダーフロー
を正の数に戻す。
このチェックにより
if
は実行されません。もし、コードが
if (newCapacity < minCapacity)
であれば、それは
true
この場合、(
newCapacity
はマイナス)なので
newCapacity
に強制されることになる。
minCapacity
に関係なく
oldCapacity
.
このオーバーフローのケースは、次のifで処理されます。いつ
newCapacity
がオーバーフローした場合、これは
true
:
MAX_ARRAY_SIZE
は次のように定義されます。
Integer.MAX_VALUE - 8
と
Integer.MIN_VALUE - (Integer.MAX_VALUE - 8) > 0
は
true
. その
newCapacity
は正しく処理されます。
hugeCapacity
メソッドは
MAX_ARRAY_SIZE
または
Integer.MAX_VALUE
.
注:これは
// overflow-conscious code
のコメントは、このメソッドで言っていることです。
関連
-
[解決済み] ファイルを作成せずに、ファイルが存在するかどうかをチェックする
-
[解決済み] 文字列の巻き方
-
[解決済み] JavaにおけるHashMapとHashtableの違いは何ですか?
-
[解決済み] Javaにおけるpublic、protected、package-private、privateの違いは何ですか?
-
[解決済み] serialVersionUIDとは何ですか、またなぜそれを使用する必要がありますか?
-
[解決済み] StringBuilderとStringBufferの違いについて
-
[解決済み] wait()とsleep()の違いについて
-
[解決済み] Javaクラスにおけるcanonical name、simple name、class nameの違いは何ですか?
-
[解決済み] JDKとJREの違いは何ですか?
-
[解決済み】HashMap、LinkedHashMap、TreeMapの違いについて
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] tempとは何ですか、またjavaにおけるtempの用途は何ですか?
-
[解決済み] javaで部分クラスを実装する方法
-
[解決済み] javacが「using unchecked or unsafe operations」という警告を出す原因は何ですか?
-
[解決済み] 親から継承したメソッドの可視性を下げることができない [重複]。
-
[解決済み] ORA-01654: インデックスを拡張できません。
-
[解決済み] Java の文字列インデックスが範囲外です。0 [閉店]
-
[解決済み] publicId と systemId の間に空白が必要です。
-
[解決済み] init-paramとcontext-param
-
[解決済み] java.sql.SQLRecoverableException: IO エラーです。NL Exceptionが発生しました
-
[解決済み] Spring ApplicationContext - リソースリーク: 'context' が閉じられない