Sjekk om en streng er numerisk i Java

1. Introduksjon

Ofte mens du opererer Strings, må vi finne ut om a String er et gyldig nummer eller ikke.

I denne opplæringen vil vi utforske flere måter å oppdage om det er gitt String er numerisk, først ved hjelp av vanlig Java, deretter vanlige uttrykk og til slutt ved hjelp av eksterne biblioteker.

Når vi er ferdige med å diskutere ulike implementeringer, bruker vi referanser for å få en ide om hvilke metoder som er optimale.

2. Forutsetninger

La oss starte med noen forutsetninger før vi går videre til hovedinnholdet.

I den siste delen av denne artikkelen bruker vi Apache Commons eksterne bibliotek som vi vil legge til sin avhengighet i pom.xml:

 org.apache.commons commons-lang3 3.9 

Den siste versjonen av dette biblioteket finner du på Maven Central.

3. Bruke vanlig Java

Kanskje den enkleste og mest pålitelige måten å sjekke om en String er numerisk eller ikke er ved å analysere den ved hjelp av Java's innebygde metoder:

  1. Integer.parseInt (streng)
  2. Float.parseFloat (String)
  3. Double.parseDouble (streng)
  4. Long.parseLong (String)
  5. nye BigInteger (String)

Hvis disse metodene ikke kaster noen NumberFormatException, så betyr det at parsingen var vellykket og String er numerisk:

offentlig statisk boolsk isNumeric (String strNum) {if (strNum == null) {return false; } prøv {doble d = Double.parseDouble (strNum); } fangst (NumberFormatException nfe) {return false; } returner sant; }

La oss se denne metoden i aksjon:

assertThat (isNumeric ("22")). isTrue (); assertThat (isNumeric ("5.05")). isTrue (); assertThat (isNumeric ("- 200")). isTrue (); assertThat (isNumeric ("10.0d")). isTrue (); assertThat (isNumeric ("22")). isTrue (); assertThat (isNumeric (null)). isFalse (); assertThat (isNumeric ("")). isFalse (); assertThat (isNumeric ("abc")). isFalse ();

I vår isNumeric () metode, vi ser bare etter verdier som er av typen Dobbelt, men denne metoden kan også endres for å se etter Heltall, Flyte, Lang og stort antall ved å bruke noen av analysemetodene vi har vervet tidligere.

Disse metodene er også diskutert i artikkelen om Java String Conversions.

4. Bruke vanlige uttrykk

La oss nå bruke regex -? \ d + (\. \ d +)? for å matche numerisk Strenger bestående av det positive eller negative heltallet og flyter.

Men dette sier seg selv at vi definitivt kan endre denne regexen for å identifisere og håndtere et bredt spekter av regler. Her holder vi det enkelt.

La oss bryte ned denne regexen og se hvordan den fungerer:

  • -? - denne delen identifiserer om det gitte tallet er negativt, bindestrek “”Søker bokstavelig talt og spørsmålstegnet“?”Markerer sin tilstedeværelse som en valgfri
  • \ d + - dette søker etter ett eller flere sifre
  • (\. \ d +)? - denne delen av regex er å identifisere float-tall. Her søker vi etter en eller flere sifre etterfulgt av en periode. Spørsmålstegnet betyr til slutt at denne hele gruppen er valgfri

Regulære uttrykk er et veldig bredt tema. For å få en kort oversikt, sjekk opplæringen vår om Java regulære uttrykk API.

For nå, la oss lage en metode som bruker ovennevnte regulære uttrykk:

privat mønster mønster = mønster.kompilere ("-? \ d + (\. \ d +)?"); public boolean isNumeric (String strNum) {if (strNum == null) {return false; } returner mønster. matcher (strNum). matcher (); }

La oss nå se på noen påstander om metoden ovenfor:

assertThat (isNumeric ("22")). isTrue (); assertThat (isNumeric ("5.05")). isTrue (); assertThat (isNumeric ("- 200")). isTrue (); assertThat (isNumeric (null)). isFalse (); assertThat (isNumeric ("abc")). isFalse ();

5. Bruke Apache Commons

I denne delen vil vi diskutere ulike metoder som er tilgjengelige i Apache Commons-biblioteket.

5.1. NumberUtils.isCreatable (String)

NumberUtils fra Apache Commons gir en statisk metode NumberUtils.isCreatable (String) som sjekker om en String er et gyldig Java-nummer eller ikke.

Denne metoden godtar:

  1. Heksadesimale tall som begynner med 0x eller 0X
  2. Oktaltall som begynner med et ledende 0
  3. Vitenskapelig notasjon (for eksempel 1.05e-10)
  4. Tall merket med en typekvalifisering (for eksempel 1L eller 2.2d)

Hvis den medfølgende strengen er null eller tom / tom, da regnes det ikke som et tall, og metoden vil komme tilbake falsk.

La oss kjøre noen tester ved hjelp av denne metoden:

assertThat (NumberUtils.isCreatable ("22")). isTrue (); assertThat (NumberUtils.isCreatable ("5.05")). isTrue (); assertThat (NumberUtils.isCreatable ("- 200")). isTrue (); assertThat (NumberUtils.isCreatable ("10.0d")). isTrue (); assertThat (NumberUtils.isCreatable ("1000L")). isTrue (); assertThat (NumberUtils.isCreatable ("0xFF")). isTrue (); assertThat (NumberUtils.isCreatable ("07")). isTrue (); assertThat (NumberUtils.isCreatable ("2.99e + 8")). isTrue (); assertThat (NumberUtils.isCreatable (null)). isFalse (); assertThat (NumberUtils.isCreatable ("")). isFalse (); assertThat (NumberUtils.isCreatable ("abc")). isFalse (); assertThat (NumberUtils.isCreatable ("22")). er Falsk (); assertThat (NumberUtils.isCreatable ("09")). er Falsk ();

Legg merke til hvordan vi får det ekte påstander om heksadesimale tall, oktale tall og vitenskapelige notasjoner i henholdsvis linje 6, 7 og 8.

Også, på linje 14, strengen “09” returnerer falsk fordi den foregående “0” indikerer at dette er et oktaltall og “09” er ikke et gyldig oktalt tall.

For hver inngang som kommer tilbake ekte med denne metoden kan vi bruke NumberUtils.createNumber (streng) som gir oss gyldig nummer.

5.2. NumberUtils.isParsable (streng)

De NumberUtils.isParsable (streng) metoden sjekker om den gitte String er analyserbar eller ikke.

Parsable tall er de som blir analysert med en hvilken som helst analysemetode som Integer.parseInt (streng), Long.parseLong (String), Float.parseFloat (String) eller Double.parseDouble (streng).

I motsetning til NumberUtils.isCreatable (), vil denne metoden ikke akseptere heksadesimale tall, vitenskapelige notasjoner eller strenger som slutter med noen type kvalifisering, det vil si 'F', 'F', 'd', 'D', 'l'eller‘L’.

La oss se på noen bekreftelser:

assertThat (NumberUtils.isParsable ("22")). isTrue (); assertThat (NumberUtils.isParsable ("- 23")). isTrue (); assertThat (NumberUtils.isParsable ("2.2")). isTrue (); assertThat (NumberUtils.isParsable ("09")). isTrue (); assertThat (NumberUtils.isParsable (null)). isFalse (); assertThat (NumberUtils.isParsable ("")). er Falsk (); assertThat (NumberUtils.isParsable ("6.2f")). isFalse (); assertThat (NumberUtils.isParsable ("9.8d")). isFalse (); assertThat (NumberUtils.isParsable ("22L")). er Falsk (); assertThat (NumberUtils.isParsable ("0xFF")). isFalse (); assertThat (NumberUtils.isParsable ("2.99e + 8")). isFalse ();

På linje 4, i motsetning til NumberUtils.isCreatable (), tallet som starter med streng “0” betraktes ikke som et oktaltall, men et normalt desimaltall, og dermed blir det sant.

Vi kan bruke denne metoden som erstatning for det vi gjorde i avsnitt 3, der vi prøver å analysere et nummer og se etter en feil.

5.3. StringUtils.isNumeric (CharSequence)

Metoden StringUtils.isNumeric (CharSequence) sjekker strengt for Unicode-sifre. Dette betyr:

  1. Eventuelle sifre fra hvilket som helst språk som er Unicode-siffer er akseptabelt
  2. Siden et desimaltegn ikke betraktes som et Unicode-siffer, er det ikke gyldig
  3. Ledende tegn (enten positive eller negative) er heller ikke akseptable

La oss nå se denne metoden i aksjon:

assertThat (StringUtils.isNumeric ("123")). isTrue (); assertThat (StringUtils.isNumeric ("١٢٣")). isTrue (); assertThat (StringUtils.isNumeric ("१२३")). isTrue (); assertThat (StringUtils.isNumeric (null)). isFalse (); assertThat (StringUtils.isNumeric ("")). er Falsk (); assertThat (StringUtils.isNumeric ("")). er Falsk (); assertThat (StringUtils.isNumeric ("12 3")). er Falsk (); assertThat (StringUtils.isNumeric ("ab2c")). er Falsk (); assertThat (StringUtils.isNumeric ("12.3")). er Falsk (); assertThat (StringUtils.isNumeric ("- 123")). er Falsk ();

Merk at inngangsparametrene i linje 2 og 3 representerer tall 123 på henholdsvis arabisk og devanagari. Siden de er gyldige Unicode-sifre, returnerer denne metoden ekte på dem.

5.4. StringUtils.isNumericSpace (CharSequence)

De StringUtils.isNumericSpace (CharSequence) kontrollerer strengt for Unicode-sifre og / eller mellomrom. Dette er det samme som StringUtils.isNumeric () med den eneste forskjellen at den godtar mellomrom også, ikke bare ledende og etterfølgende mellomrom, men også hvis de er mellom tallene:

assertThat (StringUtils.isNumericSpace ("123")). isTrue (); assertThat (StringUtils.isNumericSpace ("١٢٣")). isTrue (); assertThat (StringUtils.isNumericSpace ("")). isTrue (); assertThat (StringUtils.isNumericSpace ("")). isTrue (); assertThat (StringUtils.isNumericSpace ("12 3")). isTrue (); assertThat (StringUtils.isNumericSpace (null)). isFalse (); assertThat (StringUtils.isNumericSpace ("ab2c")). isFalse (); assertThat (StringUtils.isNumericSpace ("12.3")). isFalse (); assertThat (StringUtils.isNumericSpace ("- 123")). isFalse ();

6. Referanser

Før vi avslutter denne artikkelen, la oss gå gjennom noen referanseresultater for å hjelpe oss med å analysere hvilke av de ovennevnte metodene som er best for vårt brukstilfelle.

6.1. Enkel målestokk

Først tar vi en enkel tilnærming. Vi velger en strengverdi - for testen vi bruker Heltall.MAX_VALUE. Deretter vil den verdien bli testet mot alle våre implementeringer:

Benchmark Mode Cnt Score Error Units Benchmarking.usingCoreJava avgt 20 57.241 ± 0.792 ns / op Benchmarking.usingNumberUtils_isCreatable avgt 20 26.711 ± 1.110 ns / op Benchmarking.usingNumberUtils_isParsable avgt 20 46.577 ± 1.973 ns / op Benchmarking Benchmarking.usingStringUtils_isNumeric avgt 20 35.885 ± 1.691 ns / op Benchmarking.usingStringUtils_isNumericSpace avgt 20 31.979 ± 1.393 ns / op

Som vi ser er de dyreste operasjonene vanlige uttrykk. Etter det er vår kjerne Java-baserte løsning.

Legg også merke til at operasjonene som bruker Apache Commons-biblioteket stort sett er de samme.

6.2. Forbedret målestokk

La oss bruke et mer variert sett med tester, for en mer representativ referanse:

  • 95 verdier er numeriske (0-94 og Heltall.MAX_VALUE)
  • 3 inneholder tall, men er fortsatt feilformatert - ‘x0‘, ‘0..005′, og ‘–11
  • 1 inneholder bare tekst
  • 1 er en null

Når vi har utført de samme testene, ser vi resultatene:

Benchmark Mode Cnt Score Error Units Benchmarking.usingCoreJava avgt 20 10162.872 ± 798.387 ns / op Benchmarking.usingNumberUtils_isCreatable avgt 20 1703.243 ± 108.244 ns / op Benchmarking.usingNumberUtils_isParsable avgt 20 1589.915 ± 203.052 ns. Benchmarking.usingStringUtils_isNumeric avgt 20 1071.753 ± 8.657 ns / op Benchmarking.usingStringUtils_isNumericSpace avgt 20 1157.722 ± 24.139 ns / op

Den viktigste forskjellen er at to av testene våre - løsningen med vanlige uttrykk og den kjernede Java-baserte løsningen - har byttet plass.

Fra dette resultatet lærer vi at kasting og håndtering av NumberFormatException, som forekommer i bare 5% av tilfellene, har relativt stor innvirkning på den totale ytelsen. Så vi konkluderer med at den optimale løsningen avhenger av forventet innspill.

Vi kan også trygt konkludere med at vi skal bruke metodene fra Commons-biblioteket eller en metode implementert på samme måte for optimal ytelse.

7. Konklusjon

I denne artikkelen undersøkte vi forskjellige måter å finne ut om String er numerisk eller ikke. Vi så på begge løsningene - innebygde metoder og også eksterne biblioteker.

Som alltid kan implementeringen av alle eksempler og kodebiter gitt ovenfor, inkludert koden som brukes til å utføre referanser, bli funnet på GitHub.


$config[zx-auto] not found$config[zx-overlay] not found