Il modo più efficiente di convertire String in Integer in java

Esistono molti modi per convertire una stringa in un object intero. Qual è il più efficiente tra i seguenti:

Integer.valueOf() Integer.parseInt() org.apache.commons.beanutils.converters.IntegerConverter 

Il mio caso d’uso ha bisogno di creare wrapper Integer objects … significa no primitive int … e i dati convertiti sono usati per sola lettura.

Non perdere tempo a pensarci. Scegline uno che sembra adattarsi al resto del codice (le altre conversioni usano il metodo .parse __ () o .valueOf ()? Usalo per essere coerente).

Cercare di decidere quale sia il “migliore” riduce l’attenzione dalla soluzione del problema aziendale o dall’implementazione della funzionalità.

Non impantanarti con dettagli banali. 🙂

Nota a margine, se il tuo “caso d’uso” specifica i tipi di dati object java per il tuo codice, il tuo BA deve uscire dal tuo dominio. La necessità di BA di definire “il problema aziendale” e il modo in cui l’utente vorrebbe interagire con l’applicazione quando si affronta il problema. Gli sviluppatori determinano il modo migliore per creare tale caratteristica nell’applicazione con il codice, inclusi i tipi di dati / gli oggetti corretti per gestire i dati.

Se l’efficienza è la tua preoccupazione, la creazione di un object Integer è molto più costosa di analizzarla. Se devi creare un object Integer, non mi preoccuperei troppo di come viene analizzato.

Nota: Java 6u14 consente di aumentare la dimensione del pool Integer con un’opzione della riga di comando -Djava.lang.Integer.IntegerCache.high = 1024 ad esempio.

Nota 2: Se si stanno leggendo dati grezzi, ad esempio byte da un file o da una rete, la conversione di questi byte in una stringa è relativamente costosa. Se hai intenzione di scrivere un parser personalizzato ti suggerisco di ignorare il passaggio di conversare in una stringa e analizzare i dati di origine non elaborati.

Nota 3: Se si sta creando un intero in modo da poterlo inserire in una raccolta, è ansible evitare ciò usando GNU Trove (trove4j) che consente di memorizzare le primitive nelle raccolte, consentendo di eliminare anche la creazione di interi.

Idealmente, per ottenere le migliori prestazioni, evitare di creare qualsiasi object.

La soluzione migliore è utilizzare Integer.parseInt. Questo restituirà un int , ma questo può essere auto-boxato su un intero. Questo è leggermente più veloce di valueOf, poiché quando i numeri sono compresi tra -128 e 127 userà la cache Integer e non creerà nuovi oggetti. Il più lento è il metodo Apache.

 private String data = "99"; public void testParseInt() throws Exception { long start = System.currentTimeMillis(); long count = 0; for (int i = 0; i < 100000000; i++) { Integer o = Integer.parseInt(data); count += o.hashCode(); } long diff = System.currentTimeMillis() - start; System.out.println("parseInt completed in " + diff + "ms"); assert 9900000000L == count; } public void testValueOf() throws Exception { long start = System.currentTimeMillis(); long count = 0; for (int i = 0; i < 100000000; i++) { Integer o = Integer.valueOf(data); count += o.hashCode(); } long diff = System.currentTimeMillis() - start; System.out.println("valueOf completed in " + diff + "ms"); assert 9900000000L == count; } public void testIntegerConverter() throws Exception { long start = System.currentTimeMillis(); IntegerConverter c = new IntegerConverter(); long count = 0; for (int i = 0; i < 100000000; i++) { Integer o = (Integer) c.convert(Integer.class, data); count += o.hashCode(); } long diff = System.currentTimeMillis() - start; System.out.println("IntegerConverter completed in " + diff + "ms"); assert 9900000000L == count; } parseInt completed in 5906ms valueOf completed in 7047ms IntegerConverter completed in 7906ms 

So che questo non è tra le tue opzioni sopra. IntegerConverter è ok, ma è necessario crearne un’istanza. Dai un’occhiata a NumberUtils in Commons Lang:

Commons Lang NumberUtils

questo fornisce il metodo toInt:

 static int toInt(java.lang.String str, int defaultValue) 

che consente di specificare un valore predefinito in caso di errore.

 NumberUtils.toInt("1", 0) = 1 

Questa è la soluzione migliore che ho trovato finora.

Sono sempre stupito di quanto velocemente molti qui ignorino qualche indagine sui problemi di performance. L’analisi di un int per la base 10 è un’attività molto comune in molti programmi. Rendere questo più veloce potrebbe avere un effetto positivo notevole in molti ambienti.

Poiché parsing e int sono in realtà un compito piuttosto banale, ho cercato di implementare un approccio più diretto rispetto a quello utilizzato nell’implementazione JDK che ha base variabile. Si è rivelato essere più veloce del doppio e dovrebbe altrimenti comportarsi esattamente come Integer.parseInt ().

 public static int intValueOf( String str ) { int ival = 0, idx = 0, end; boolean sign = false; char ch; if( str == null || ( end = str.length() ) == 0 || ( ( ch = str.charAt( 0 ) ) < '0' || ch > '9' ) && ( !( sign = ch == '-' ) || ++idx == end || ( ( ch = str.charAt( idx ) ) < '0' || ch > '9' ) ) ) throw new NumberFormatException( str ); for(;; ival *= 10 ) { ival += '0'- ch; if( ++idx == end ) return sign ? ival : -ival; if( ( ch = str.charAt( idx ) ) < '0' || ch > '9' ) throw new NumberFormatException( str ); } } 

Per ottenere un object intero, usa autorboxing o esplicito

Interger.valueOf( intValueOf( str ) ) .

Se l’efficienza è la tua preoccupazione, usa int: è molto più veloce di Integer.

Altrimenti, la class Integer offre almeno un paio di modi chiari e puliti:

 Integer myInteger = new Integer(someString); Integer anotherInteger = Integer.valueOf(someOtherString); 

Ecco un buon articolo che confronta le prestazioni dei diversi metodi di parsing degli interi

Ed ecco il codice utilizzato, con controlli di overflow / underflow.

 public static int parseInt( final String s ) { if ( string == null ) throw new NumberFormatException( "Null string" ); // Check for a sign. int num = 0; int sign = -1; final int len = s.length( ); final char ch = s.charAt( 0 ); if ( ch == '-' ) { if ( len == 1 ) throw new NumberFormatException( "Missing digits: " + s ); sign = 1; } else { final int d = ch - '0'; if ( d < 0 || d > 9 ) throw new NumberFormatException( "Malformsd: " + s ); num = -d; } // Build the number. final int max = (sign == -1) ? -Integer.MAX_VALUE : Integer.MIN_VALUE; final int multmax = max / 10; int i = 1; while ( i < len ) { int d = s.charAt(i++) - '0'; if ( d < 0 || d > 9 ) throw new NumberFormatException( "Malformsd: " + s ); if ( num < multmax ) throw new NumberFormatException( "Over/underflow: " + s ); num *= 10; if ( num < (max+d) ) throw new NumberFormatException( "Over/underflow: " + s ); num -= d; } return sign * num; } 

E implementazione ancora più veloce, senza controlli di overflow / underflow.

 public static int parseInt( final String s ) { // Check for a sign. int num = 0; int sign = -1; final int len = s.length( ); final char ch = s.charAt( 0 ); if ( ch == '-' ) sign = 1; else num = '0' - ch; // Build the number. int i = 1; while ( i < len ) num = num*10 + '0' - s.charAt( i++ ); return sign * num; } 

Ho provato un confronto di valueOf, parseInt, Ints.tryParse, NumberUtils.createInteger e NumberUtils.toInt con il programma qui sotto. Ero su jdk 1.8.0

Come previsto, i metodi che non avevano bisogno di creare un object Integer erano i più veloci. I miei risultati sono stati:

 valueOf took: 77 parseInt took: 61 Ints.tryParse took: 117 numberUtils.createInteger took: 169 numberUtils.toInt took: 63 

Quindi il riassunto è:

Se riesci a ottenere usando un int, usa Integer.parseInt.

Se hai assolutamente bisogno di un intero, usa Integer.valueOf

Se hai bisogno della comodità di non gestire le eccezioni durante l’analisi, o se non sei sicuro del formato dell’input (ovvero è una stringa che non deve essere un numero) usa Ints.tryParse

Il codice che ho usato era:

 public class HelloWorld { public static int limit = 1000000; public static String sint = "9999"; public static void main(String[] args) { long start = System.currentTimeMillis(); for (int i = 0; i < limit; i++) { Integer integer = Integer.valueOf(sint); } long end = System.currentTimeMillis(); System.out.println("valueOf took: " + (end - start)); start = System.currentTimeMillis(); for (int i = 0; i < limit; i++) { int integer = Integer.parseInt(sint); } end = System.currentTimeMillis(); System.out.println("parseInt took: " + (end - start)); start = System.currentTimeMillis(); for (int i = 0; i < limit; i++) { int integer = Ints.tryParse(sint); } end = System.currentTimeMillis(); System.out.println("Ints.tryParse took: " + (end - start)); start = System.currentTimeMillis(); for (int i = 0; i < limit; i++) { Integer integer = NumberUtils.createInteger(sint); } end = System.currentTimeMillis(); System.out.println("numberUtils.createInteger took: " + (end - start)); start = System.currentTimeMillis(); for (int i = 0; i < limit; i++) { int integer = NumberUtils.toInt(sint); } end = System.currentTimeMillis(); System.out.println("numberUtils.toInt took: " + (end - start)); } } 

ParseInt restituisce un int, non un java.lang.Integer, quindi se usi il metodo tat dovresti fare

 new Integer (Integer.parseInt(number)); 

Ho sentito molte volte che chiamare Integer.valueOf () invece di new Integer () è meglio per motivi di memoria (questo è in arrivo per pmd)

In JDK 1.5, chiamare il nuovo numero intero () causa l’allocazione della memoria. Integer.valueOf () è più adatto alla memoria.

http://pmd.sourceforge.net/rules/migrating.html

In aggiunta a ciò, Integer.valueOf consente il caching, poiché i valori da -127 a 128 sono garantiti per avere istanze memorizzate nella cache. (da java 1.5)

Herro – un po ‘nuovo per Java, quindi perdona la mia ignoranza.

Stavo cercando un modo per analizzare una stringa mista (lettere e numeri) in un INT (un po ‘come fa JavaScript). Non ho trovato nulla nei file JAVADOC quindi dopo molte ricerche ho appena scritto una funzione che lo fa:

 // This function takes a string mixed with numbers and letters and returns an INT with // the first occurrence of a number (INT) in said string, ignoring the rest; // -- Basically, loop checks if char is a digit, if yes, puts digit back into new array, if no, puts a whitespace in its place // this creates an array with only digits; By converting it to a string and then trimming whitespaces, it gets parsed into an INT public static int mixedStringToInt (String str) { boolean flag = true; boolean isNumber = false; final String refNumbers = "0123456789"; int strlen = str.length(); char[] numberArray = new char[strlen]; char[] stringArray = str.toCharArray(); for (int i = 0; i < strlen;i++){ if(refNumbers.indexOf(stringArray[i]) > 0 && flag){ // if current char is a digit isNumber = true; while (flag){ numberArray[i] = stringArray[i]; if(i+1 >= strlen || refNumbers.indexOf(stringArray[i+1]) < 0) flag = false; i++; } } else { // if current char is not a digit numberArray[i] = ' '; } } if (isNumber){ return Integer.valueOf(new String(numberArray).trim()); } else return 0; } 

E 'utile per qualcuno oltre a me? Ho perso tempo scrivendo questo perché esiste già un metodo che fa ciò che volevo fare?

Un altro modo è questo metodo:

 public class stringtoInteger { private static int stringtoInteger(String x) { String value = ""; for (int i = 0; i < x.length(); i++) { char character = x.charAt(i); if (Character.isDigit(character)) { value = value + character; } } return Integer.parseInt(value); } } 

Spero che sia d'aiuto!