Trabajar con números enteros
Como clase contenedora, Integer proporciona varios métodos para trabajar con int , así como varios métodos para convertir int en String y String en int . La clase tiene dos constructores:-
public Integer(int i) , donde i es un valor primitivo para inicializar. Este crea un objeto Integer que se inicializa con el valor int .
-
public Integer(String s) lanza NumberFormatException . Aquí s es una representación de cadena del valor int . Este constructor crea un objeto Integer que se inicializó con el valor int proporcionado por la representación de cadena .
Creación de objetos enteros
Existen diferentes opciones de creación de objetos Integer . Uno de los más utilizados es el más sencillo. Aquí hay un ejemplo:Integer myInteger = 5;
La inicialización de la variable Integer en este caso es similar a la inicialización de la variable int primitiva . Por cierto, puedes inicializar una variable Integer con el valor de un int . Aquí hay un ejemplo:
int myInt = 5;
Integer myInteger = myInt;
System.out.println(myInteger);
El resultado aquí es:
Integer myInteger = new Integer(5);
Puedes hacer con la variable Integer lo mismo que con int (suma, resta, multiplica, divide, incrementa, disminuye). Sin embargo, es importante recordar que Integer es un tipo de datos de referencia y una variable de este tipo puede ser nula. En este caso, es mejor abstenerse de realizar este tipo de operaciones.
Integer myInteger1 = null;
Integer myInteger2 = myInteger1 + 5;
Aquí obtendremos una excepción:
Constantes de clase entera
La clase Integer proporciona varias constantes y métodos para trabajar con números enteros. Aquí están:-
TAMAÑO significa el número de bits en el sistema numérico de dos dígitos ocupados por el tipo int
-
BYTES es el número de bytes en un sistema numérico de dos dígitos ocupados por el tipo int
-
MAX_VALUE es el valor máximo que puede contener el tipo int
-
MIN_VALUE es el valor mínimo que puede contener el tipo int
-
TYPE devuelve un objeto de tipo Clase de tipo int
Métodos más útiles de clase entera
Ahora echemos un vistazo a los métodos más utilizados de la clase Integer . Supongo que los más populares son los métodos para convertir un número a partir de un String , o viceversa.-
static int parseInt(String s) este método convierte String en int . Si la conversión no es posible, se lanzará NumberFormatException .
-
static int parseInt(String s, int radix) este método también convierte el parámetro s en un int . El parámetro de base indica que el sistema numérico se escribió originalmente.
-
static Integer valueOf(int i) devuelve un entero cuyo valor es i ;
-
static Integer valueOf(String s) funciona como parseInt(String s) , pero el resultado será Integer , no int ;
-
static Integer valueOf(String s, int radix) funciona igual que parseInt(String s, int radix) , pero el resultado es un Integer , no un int .
¿Hay algún problema con la clase Integer? Ah, sí, hay...
Entonces, hay dos tipos de números enteros (que caben en 32 bits) en Java: int e Integer . Para comprender los detalles de cada uno de ellos, necesitamos saber lo siguiente sobre el modelo de memoria JVM: todo lo que declara se almacena en Stack Memory (pila JVM específica para cada subproceso) o en Heap Space. Los tipos primitivos ( int , long , float , boolean , double , char , byte , etc.) se almacenan en la memoria de pila. Todos los objetos y matrices se almacenan en Heap Space. Las referencias a estos objetos y las matrices necesarias para los métodos se almacenan en Stack. Entonces. ¿Por qué nos importa? Bueno, verá, Stack es más pequeño que Heap (una desventaja), pero es mucho más rápido asignar valores en Stack que en Heap (una ventaja). Comencemos con un tipo primitivo int . Ocupa exactamente 32 bits. Eso es 32/8=4 bytes. Porque es un tipo primitivo. Ahora, consideremos el número entero . Es un objeto, con gastos generales y alineaciones adicionales. He usado un jol de biblioteca para medir su tamaño:public static void main(String[] args) {
System.out.println(ClassLayout.parseInstance(Integer.valueOf(1)).toPrintable());
}
y resultó ocupar 16 bytes:
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());
}
Y el resultado es 4016 bytes:
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());
}
Y el resultado es 20040 bytes (¡nuevamente, 4 veces más!):
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());
}
Y el resultado es 4040 bytes (¡casi lo mismo que 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
Los puntos de referencia:
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;
}
Los resultados:
@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]
Los resultados: la matriz de primitivas es más de 4 veces más rápida que la matriz de valores en cuadros ( Integer s); casi seis veces más rápido que ArrayList de valores en cuadros ( Integer s); y dos veces más rápido que TIntArrayList (que en realidad decora una serie de entradas primitivas). Por lo tanto, si necesita una estructura de datos para almacenar una colección de valores enteros y su tamaño no va a cambiar, use un int[] ; Si el tamaño va a cambiar, es posible que desee utilizar la biblioteca tove4j con TIntArrayList . Y aquí llega el final de mi ensayo donde explico las desventajas de usar el tipo Integer . Hay algunos métodos estáticos interesantes de Integer , de los que debería hablar antes de terminar. public static Integer getInteger(String nm, int val) no hace lo que uno podría pensar, pero recupera un valor entero de una propiedad del sistema. Val es el valor predeterminado en caso de que esta propiedad no esté configurada. public static String toBinaryString(int i) devuelve una cadena con una representación binaria de un número. Existen métodos para recuperar representaciones basadas en 16 ( toHexString ) y basadas en 8 ( toOctalString ). Existe un método para analizar una cadena en un int . Incluso si la cadena es una representación basada en 10 bases. A continuación se muestran algunos ejemplos: Integer.parseInt("-FF", 16) devuelve -255 Integer.parseInt("+42", 10) devuelve 42 Integer.parseInt("1100110", 2) devuelve 102