Lavorare con numeri interi
Come classe wrapper, Integer fornisce vari metodi per lavorare con int , oltre a una serie di metodi per convertire int in String e String in int . La classe ha due costruttori:-
public Integer(int i) , dove i è un valore primitivo da inizializzare. Questo crea un oggetto Integer che viene inizializzato con il valore int .
-
public Integer(String s) genera NumberFormatException . Ecco una rappresentazione di stringa del valore int . Questo costruttore crea un oggetto Integer che è stato inizializzato con il valore int fornito dalla rappresentazione di stringa .
Creazione di oggetti interi
Esistono diverse opzioni per la creazione di oggetti Integer . Uno dei più utilizzati è quello più semplice. Ecco un esempio:Integer myInteger = 5;
L'inizializzazione della variabile Integer in questo caso è simile all'inizializzazione della variabile int primitiva . A proposito, puoi inizializzare una variabile intera con il valore di un int . Ecco un esempio:
int myInt = 5;
Integer myInteger = myInt;
System.out.println(myInteger);
L'output qui è:
Integer myInteger = new Integer(5);
Puoi fare con la variabile Integer lo stesso che con int (aggiungi, sottrai, moltiplica, dividi, incrementa, decrementa). Tuttavia, è importante ricordare che Integer è un tipo di dati di riferimento e una variabile di questo tipo può essere nulla. In questo caso è meglio astenersi da tali operazioni.
Integer myInteger1 = null;
Integer myInteger2 = myInteger1 + 5;
Qui otterremo un'eccezione:
Costanti di classe intera
La classe Integer fornisce varie costanti e metodi per lavorare con i numeri interi. Eccoli:-
DIMENSIONE indica il numero di bit nel sistema numerico a due cifre occupato dal tipo int
-
BYTES è il numero di byte nel sistema numerico a due cifre occupati dal tipo int
-
MAX_VALUE è il valore massimo che il tipo int può contenere
-
MIN_VALUE è il valore minimo che il tipo int può contenere
-
TYPE restituisce un oggetto di tipo Class dal tipo int
Metodi più utili della classe intera
Diamo ora uno sguardo ai metodi più utilizzati della classe Integer . I più popolari, presumo, sono i metodi per convertire un numero da un String o viceversa.-
static int parseInt(String s) questo metodo converte String in int . Se la conversione non è possibile, verrà lanciata NumberFormatException .
-
static int parseInt(String s, int radix) questo metodo converte anche il parametro s in un int . Il parametro radice indica il sistema numerico s originariamente scritto.
-
static Integer valueOf(int i) restituisce un intero il cui valore è i ;
-
static Integer valueOf(String s) funziona come parseInt(String s) , ma il risultato sarà Integer , non int ;
-
static Integer valueOf(String s, int radix) funziona allo stesso modo di parseInt(String s, int radix) , ma il risultato è un Integer , non un int .
C'è qualche problema con la classe Integer? Oh sì, c'è...
Quindi ci sono due tipi di numeri interi (che rientrano in 32 bit) in Java: int e Integer . Per comprendere le specifiche di ciascuno di essi dobbiamo sapere quanto segue sul modello di memoria JVM: tutto ciò che dichiari viene archiviato nella Stack Memory (stack JVM specifico per ciascun thread) o nello spazio Heap. I tipi primitivi ( int , long , float , boolean , double , char , byte , ecc.) sono archiviati nella memoria Stack. Tutti gli oggetti e gli array sono archiviati nello spazio heap. I riferimenti a questi oggetti e array necessari per i metodi sono archiviati in Stack. COSÌ. Perché ci interessa? Bene, vedi, Stack è più piccolo di Heap (un contro), ma è molto più veloce allocare valori in Stack che in Heap (un professionista). Cominciamo con un tipo primitivo int . Occupa esattamente 32 bit. Questo è 32/8=4 byte. Perché è un tipo primitivo. Consideriamo ora Integer . È un oggetto, con spese generali e allineamenti aggiuntivi. Ho usato una libreria jol per misurarne le dimensioni:public static void main(String[] args) {
System.out.println(ClassLayout.parseInstance(Integer.valueOf(1)).toPrintable());
}
e si è scoperto che occupava 16 byte:
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());
}
E il risultato è 4016 byte:
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());
}
E il risultato è 20040 byte (di nuovo, 4 volte di più!):
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());
}
E il risultato è 4040 byte (quasi uguale a 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
I parametri di riferimento:
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;
}
I risultati:
@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]
I risultati: l'array di primitive è più di 4 volte più veloce dell'array di valori boxed ( Integer s); quasi sei volte più veloce di ArrayList di valori boxed ( Integer s); e due volte più veloce di un TIntArrayList (che in realtà decora una serie di int primitivi). Pertanto, se hai bisogno di una struttura dati per memorizzare una raccolta di valori interi e la sua dimensione non cambierà, usa un int[] ; se la dimensione cambierà, potresti voler utilizzare la libreria tove4j con TIntArrayList . E qui arriva la fine del mio saggio in cui spiego gli svantaggi dell'utilizzo del tipo Integer . Esistono alcuni metodi statici interessanti di Integer , di cui dovrei parlare prima di finire. public static Integer getInteger(String nm, int val) non fa quello che si potrebbe pensare, ma recupera un valore intero di una proprietà di sistema. Val è l'impostazione predefinita nel caso in cui questa proprietà non sia impostata. public static String toBinaryString(int i) restituisce una stringa con una rappresentazione binaria di un numero. Esistono metodi per il recupero di rappresentazioni in base 16 ( toHexString ) e in base 8 ( toOctalString ). Esiste un metodo per analizzare una String in un int . Anche se la stringa è una rappresentazione non basata su radice 10. Ecco alcuni esempi: Integer.parseInt("-FF", 16) restituisce -255 Integer.parseInt("+42", 10) restituisce 42 Integer.parseInt("1100110", 2) restituisce 102
GO TO FULL VERSION