整数の操作
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);
ここでの出力は次のとおりです。
Integer myInteger = new Integer(5);
Integer変数でも、 intと同じように 操作できます(加算、減算、乗算、除算、増分、減分)。ただし、 Integer は参照データ型であり、この型の変数は null になる可能性があることに留意することが重要です。この場合、そのような操作は控えた方が良いでしょう。
Integer myInteger1 = null;
Integer myInteger2 = myInteger1 + 5;
ここで例外が発生します。
整数クラス定数
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 が最初に書き込まれたことを示します。
-
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 ビットに収まる) 整数にはintとIntegerの 2 つの型があります。それぞれの詳細を理解するには、JVM メモリ モデルについて次のことを知る必要があります。宣言したものはすべて、スタック メモリ (各スレッドに固有の JVM スタック) またはヒープ スペースのいずれかに保存されます。プリミティブ型 ( int、long、float、boolean、double、char、byteなど) はスタック メモリに保存されます。すべてのオブジェクトと配列はヒープ スペースに保存されます。メソッドに必要なこれらのオブジェクトと配列への参照はスタックに保存されます。それで。なぜ気にするのでしょうか?スタックはヒープ (短所) よりも小さいですが、ヒープ (プロ) よりもスタックに値を割り当てる方がはるかに高速です。プリミティブ型intから始めましょう。正確に 32 ビットを占めます。つまり、32/8=4 バイトです。原始的なタイプなので。次に、Integer について考えてみましょう。これはオブジェクトですが、余分なオーバーヘッドと配置が伴います。サイズを測定するためにライブラリ jol を使用しました。public static void main(String[] args) {
System.out.println(ClassLayout.parseInstance(Integer.valueOf(1)).toPrintable());
}
そして、それは 16 バイトを占めることが判明しました。
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 バイトになります。
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 倍です!)。
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[]とほぼ同じです!)。
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;
}
結果:
@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 を返します。