CodeGym/Java Blog/ランダム/Java.lang.Integer クラス
John Squirrels
レベル 41
San Francisco

Java.lang.Integer クラス

ランダム グループに公開済み
人のメンバー
Java データ型は、条件に応じてプリミティブと参照 (クラス) の 2 つのブロックに分割できます。Java には、整数 ( byteshortintlong )、浮動小数点数 ( floatdouble )、論理データ型 ( boolean )、文字データ型 ( char )など、いくつかのプリミティブ データ型があります。おそらく、各プリミティブ データ型には独自のラッパー クラスがあることはすでにご存知でしょう。Java オブジェクト内のその原始的な兄弟を「ラップ」または変換する参照データ型。Integer は、int という名前のプリミティブ クラスのラッパー クラスです。英語のIntegerは整数を意味します。それらは、正、負、または 0 のいずれかになります。残念ながら、Java の整数は整数を意味しません。Java の整数は 32 ビットに収まる整数です。より大きな数値が必要な場合は、Java Long数値を使用してください。彼らは自由に使える 64 ビットを持っています。運悪くさらに大きな数が必要になった場合は、Java でBigInteger を使用できます。

整数の操作

Integer はラッパー クラスとして、int を操作するためのさまざまなメソッドと、int をStringに変換するためのメソッド、およびStringをintに変換するための多数のメソッドを提供します。このクラスには 2 つのコンストラクターがあります。
  • public Integer(int i)、ここでi は初期化するプリミティブ値です。これは、int値で初期化されるIntegerオブジェクトを作成します。

  • public Integer(String s) はNumberFormatExceptionをスローします。ここで、sはint値の文字列表現です。このコンストラクターは、文字列表現によって提供されるint値で初期化されたIntegerオブジェクトを作成します。

整数オブジェクトの作成

さまざまな整数オブジェクト作成オプションがあります。最も一般的に使用されるものの 1 つは、最も簡単なものです。以下に例を示します。
Integer myInteger = 5;
この場合のInteger変数 の初期化は、プリミティブ int変数の初期化と似ています。ちなみに、Integer変数をintの値で初期化することもできます。以下に例を示します。
int myInt = 5;
Integer myInteger = myInt;
System.out.println(myInteger);
ここでの出力は次のとおりです。
5
実際、ここでは自動パッキングを観察できます。また、コンストラクターとnewキーワード を使用して、他のオブジェクトと同じようにIntegerオブジェクトを作成することもできます。
Integer myInteger = new Integer(5);
Integer変数でも、 intと同じように 操作できます(加算、減算、乗算、除算、増分、減分)。ただし、 Integer は参照データ型であり、この型の変数は null になる可能性があることに留意することが重要です。この場合、そのような操作は控えた方が良いでしょう。
Integer myInteger1  = null;
Integer myInteger2 = myInteger1 + 5;
ここで例外が発生します。
スレッド「メイン」java.lang.NullPointerException での例外

整数クラス定数

Integerクラス、整数を操作するためのさまざまな定数とメソッドを提供します。どうぞ:
  • SIZE は、int型が占める 2 桁の数体系のビット数を意味します。

  • BYTES は、 int型が占める 2 桁の数値体系のバイト数です。

  • MAX_VALUE はint型が保持できる最大値です。

  • MIN_VALUE はint型が保持できる最小値です。

  • TYPE はint型からClass型のオブジェクトを返します。

整数クラスの最も便利なメソッド

ここで、 Integerクラスの最もよく使用されるメソッドを見てみましょう。その中で最も人気があるのは、 Stringから数値を変換するメソッド、またはその逆のメソッドだと思います。
  • static int parseInt(String s)このメソッドはStringをintに変換します。変換できない場合は、NumberFormatExceptionがスローされます。

  • static int parseInt(String s, int radix)このメソッドは、sパラメータをintに変換します。radixパラメータは、数値体系s が最初に書き込まれたことを示します。

parseIntに加えて、いくつかのバリエーションで非常によく似たvalueOfメソッドもあります。ただし、 valueOfの結果はIntegerになり、parseInt はintになります。
  • static Integer valueOf(int i) は、値がiである整数を返します。

  • static Integer valueOf(String s) はparseInt(String s)と同様に機能しますが、結果はintではなくIntegerになります。

  • static Integer valueOf(String s, int radix) はparseInt(String s, int radix)と同じように機能しますが、結果はintではなくIntegerになります。

Integerクラスに問題があるのでしょうか?ああ、それはあります…

したがって、Java には (32 ビットに収まる) 整数にはintIntegerの 2 つの型があります。それぞれの詳細を理解するには、JVM メモリ モデルについて次のことを知る必要があります。宣言したものはすべて、スタック メモリ (各スレッドに固有の JVM スタック) またはヒープ スペースのいずれかに保存されます。プリミティブ型 ( intlongfloatbooleandoublecharbyteなど) はスタック メモリに保存されます。すべてのオブジェクトと配列はヒープ スペースに保存されます。メソッドに必要なこれらのオブジェクトと配列への参照はスタックに保存されます。それで。なぜ気にするのでしょうか?スタックはヒープ (短所) よりも小さいですが、ヒープ (プロ) よりもスタックに値を割り当てる方がはるかに高速です。プリミティブ型intから始めましょう。正確に 32 ビットを占めます。つまり、32/8=4 バイトです。原始的なタイプなので。次に、Integer について考えてみましょう。これはオブジェクトですが、余分なオーバーヘッドと配置が伴います。サイズを測定するためにライブラリ jol を使用しました。
public static void main(String[] args) {
 	System.out.println(ClassLayout.parseInstance(Integer.valueOf(1)).toPrintable());
}
そして、それは 16 バイトを占めることが判明しました。
java.lang.Integer オブジェクト内部: OFF SZ TYPE DESCRIPTION VALUE 0 8 (オブジェクト ヘッダー: マーク) 0x000000748c90e301 (ハッシュ: 0x748c90e3; age: 0) 8 4 (オブジェクト ヘッダー: クラス) 0x000492a0 12 4 int Integer.value 1 インスタンス サイズ: 16バイト
何?!メモリは4倍です!しかし、そこでやめてはいけません。Java 開発者として、私たちは通常、単一の整数の使用をやめることはありません。私たちが本当に望んでいるのは、それらをたくさん使うことです。シーケンスのように。たとえば、配列内。またはリスト。配列はリストと同様にヒープに保存されます。したがって、割り当てにはほぼ同じ時間がかかります。右?しかし、より多くのメモリを割り当てる必要がある場合はどうすればよいでしょうか? 1000 個のプリミティブint値の配列がどれくらいのスペースを必要とするかを確認してみましょう。
public static void main(String[] args) {
    	int[] array = new int[1000];
    	for (int i = 0; i < 1000; i++) array[i] = i;                System.out.println(ClassLayout.parseInstance(array).toPrintable());
}
結果は 4016 バイトになります。
OFF SZ タイプの説明値 0 8 (オブジェクト ヘッダー: マーク) 0x0000000000000001 (非バイアス可能、年齢: 0) 8 4 (オブジェクト ヘッダー: クラス) 0x00006c38 12 4 (配列長) 1000 12 4 (アライメント/パディング ギャップ) 16 4000 int [I.<elements> N/A インスタンス サイズ: 4016 バイト スペース損失: 内部 4 バイト + 外部 0 バイト = 合計 4 バイト
単一の int が 4 バイト必要であることを考えると、それはある程度理にかなっています。1000 個の整数のArrayList<Integer>はどうなるでしょうか? みてみましょう:
public static void main(String[] args) {
	List<Integer> list = new ArrayList<>(1000);
	for (int i = 0; i < 1000; i++) list.add(i);
      System.out.println(GraphLayout.parseInstance(list).toFootprint());
}
結果は 20040 バイトになります (これも 4 倍です!)。
java.util.ArrayList@66d3c617d フットプリント: COUNT AVG SUM DESCRIPTION 1 4016 4016 [Ljava.lang.Object; 1000 16 16000 java.lang.Integer 1 24 24 java.util.ArrayList 1002 20040 (合計)
したがって、ArrayList<Integer> は4 倍のメモリ領域を占有します。それは良いことではありません。それでも、要素を追加したり削除したりできるため、リストの方が簡単です。ああ、Java…なぜすべてを箱詰めする必要があるのでしょうか?! しかし、忘れがちですが、Java は素晴らしいものであり、その素晴らしさは、使用できるオープン ソース ライブラリが豊富にあることにあります。Trove4j もその 1 つです。内部的にint[]データを持つTIntArrayListがあります。サイズを測ってみましょう。
public static void main(String[] args) {
	TIntList list = new TIntArrayList(1000);
	for (int i = 0; i < 1000; i++) list.add(i);
	System.out.println(GraphLayout.parseInstance(list).toFootprint());
}
結果は 4040 バイトになります (単にint[]とほぼ同じです!)。
gnu.trove.list.array.TIntArrayList@7440e464d フットプリント: COUNT AVG SUM DESCRIPTION 1 4016 4016 [I 1 24 24 gnu.trove.list.array.TIntArrayList 2 4040 (合計)
したがって、最終的には両方の長所を活かすことができます。占有スペースが 4 倍少ない整数のリスト。これにはIntegerインスタンスは関係ありません。intのみ。私たち Java 開発者はメモリを非常に重視しています…しかし、パフォーマンスも重視しています。jmh という控えめな名前の素晴らしいマイクロベンチマーク ライブラリがあり、コードのパフォーマンスを測定できます。まず、ボックス化されたかどうかに関係なく、2 つのランダムな整数の合計を計算するパフォーマンスを比較してみましょう。 jmh の構成は次のとおりです。
benchmark {
	configurations {
    	main {
        	warmups = 5 // number of warmup iterations
        	iterations = 50 // number of iterations
        	iterationTime = 500 // time in seconds per iteration
        	iterationTimeUnit = "ns" // time unit for iterationTime
ベンチマーク:
private static final Random random = new Random();

@Benchmark
public int testPrimitiveIntegersSum() {
	int a = random.nextInt();
	int b = random.nextInt();
	return a + b;
}

@Benchmark
public Integer testBoxedIntegersSum() {
	Integer a = random.nextInt();
	Integer b = random.nextInt();
	return a + b;
}
結果:
main: test.SampleJavaBenchmark.testBoxedIntegersSum 5693337.344 ±(99.9%) 1198774.178 ops/s [平均] (最小、平均、最大) = (1092314.989、5693337.344、12001683.428)、stdev = 2421 583.144 CI (99.9%): [4494563.166、6892111.522] (正規分布を仮定) main: test.SampleJavaBenchmark.testPrimitiveIntegersSum 15295010.959 ±(99.9%) 2555447.456 ops/s [平均] (最小、平均、最大) = (4560097.059, 15295010.959, 24283809.447) 、stdev = 5162130.283 CI (99.9%): [12739563.502、17850458.415] (正規分布を仮定)
したがって、平均して、プリミティブ整数の割り当てと合計は、ボックス化された整数の 2 倍以上高速になります。ここで、コレクション (または 1000 個の整数の配列) の作成と合計の計算のパフォーマンスを比較してみましょう。
@Benchmark
public int testPrimitiveArray() {
	int[] array = new int[1000];
	for (int i = 0; i < 1000; i++) array[i] = i;
	int sum = 0;
	for (int x : array) sum += x;
	return sum;
}
11933.545 ops/s [Average]


@Benchmark
public int testBoxesArray() {
	Integer[] array = new Integer[1000];
	for (int i = 0; i < 1000; i++) array[i] = i;
	int sum = 0;
	for (int x : array) sum += x;
	return sum;
}
2733.312 ops/s [Average]


@Benchmark
public int testList() {
	List<Integer> list = new ArrayList<>(1000);
	for (int i = 0; i < 1000; i++) list.add(i);
	int sum = 0;
	for (int x : list) sum += x;
	return sum;
}
2086.379 ops/s [Average]


@Benchmark
public int testTroveIntList() {
	TIntList list = new TIntArrayList(1000);
	for (int i = 0; i < 1000; i++) list.add(i);
	int sum = 0;
	for (int i = 0; i < 1000; i++) sum += list.get(i);
	return sum;
}
5727.979 ops/s [Average]
結果: プリミティブ配列は、ボックス化された値 ( Integer ) の配列より 4 倍以上高速です。ボックス化された値 ( Integer )のArrayListよりもほぼ 6 倍高速です。TIntArrayList (実際にはプリミティブ int の配列を修飾します)の 2 倍の速度です。したがって、整数値のコレクションを格納するデータ構造が必要で、そのサイズが変更されない場合は、 int []を使用します。サイズが変更される場合は、TIntArrayListとともに tove4j ライブラリを使用するとよいでしょう。そして、ここで私のエッセイの終わりに来て、整数型を使用することの短所を説明します。Integerには興味深い静的メソッドがいくつかあります。それについては、終了する前に説明しておきます。 public static Integer getInteger(String nm, int val) は、一般的に考えられているようなことは行いませんが、システム プロパティの整数値を取得します。このプロパティが設定されていない場合のデフォルトは Valです。public static String toBinaryString(int i) は、数値のバイナリ表現を含むStringを返します。16 ベース ( toHexString ) および 8 ベース ( toOctalString ) 表現を取得するためのメソッドがあります。String をintに解析するメソッドがあります。文字列が非 10 基数ベースの表現であっても。例をいくつか示します。 Integer.parseInt("-FF", 16)は -255 を返します。 Integer.parseInt("+42", 10) は42 を返します。 Integer.parseInt("1100110", 2)は 102 を返します。
コメント
  • 人気
  • 新規
  • 古い
コメントを残すには、サインインしている必要があります
このページにはまだコメントがありません