Skontrolujte, či je reťazec v jazyku Java číselný

1. Úvod

Často pri prevádzke Strings, musíme zistiť, či a String je platné číslo alebo nie.

V tejto príručke preskúmame niekoľko spôsobov, ako zistiť, či je daná String je číselná hodnota, najskôr pomocou obyčajnej Javy, potom pomocou regulárnych výrazov a nakoniec pomocou externých knižníc.

Keď skončíme diskusiu o rôznych implementáciách, pomocou benchmarkov získate predstavu o tom, ktoré metódy sú optimálne.

2. Predpoklady

Začnime s niekoľkými predpokladmi, než sa dostaneme k hlavnému obsahu.

V druhej časti tohto článku budeme používať externú knižnicu Apache Commons, pre ktorú do nej pridáme jej závislosť pom.xml:

 org.apache.commons commons-lang3 3.9 

Najnovšiu verziu tejto knižnice nájdete na serveri Maven Central.

3. Používanie obyčajnej Javy

Možno najjednoduchší a najspoľahlivejší spôsob, ako skontrolovať, či a String je číselný alebo nie, jeho analýzou pomocou vstavaných metód jazyka Java:

  1. Integer.parseInt (reťazec)
  2. Float.parseFloat (reťazec)
  3. Double.parseDouble (reťazec)
  4. Long.parseLong (reťazec)
  5. nový BigInteger (reťazec)

Ak tieto metódy žiadne nevyhodia NumberFormatException, potom to znamená, že analýza bola úspešná a String je číselné:

public static boolean isNumeric (String strNum) {if (strNum == null) {return false; } skúsiť {double d = Double.parseDouble (strNum); } catch (NumberFormatException nfe) {return false; } návrat pravdivý; }

Pozrime sa na túto metódu v akcii:

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 ();

V našom isNumeric () metóda, iba kontrolujeme, či sú hodnoty typu Dvojitý, ale túto metódu je možné upraviť aj na kontrolu Celé číslo, Plavák, Dlhé a veľké čísla pomocou ktorejkoľvek z metód analýzy, ktoré sme zaradili skôr.

Tieto metódy sú tiež diskutované v článku Java String Conversions.

4. Používanie regulárnych výrazov

Teraz použijeme regex -? \ d + (\. \ d +)? aby zodpovedal číselnému Struny pozostávajúci z kladného alebo záporného celého čísla a pohyblivých plôch.

Je však samozrejmé, že tento regulárny výraz môžeme určite upraviť tak, aby identifikoval a spracoval širokú škálu pravidiel. Tu to zjednodušíme.

Poďme si rozdeliť tento regulárny výraz a pozrime sa, ako to funguje:

  • -? - táto časť identifikuje, či je dané číslo záporné, pomlčka „„Vyhľadáva pomlčku doslovne a otáznik“?”Označuje jeho prítomnosť ako voliteľnú
  • \ d + - toto vyhľadáva jednu alebo viac číslic
  • (\. \ d +)? - táto časť regulárneho výrazu má identifikovať čísla float. Tu hľadáme jednu alebo viac číslic, za ktorými nasleduje bodka. Otáznik nakoniec znamená, že táto úplná skupina je voliteľná

Regulárne výrazy sú veľmi širokou témou. Stručný prehľad nájdete v našom výučbe rozhrania API pre regulárne výrazy Java.

Teraz si vytvorme metódu pomocou vyššie uvedeného regulárneho výrazu:

private Pattern pattern = Pattern.compile ("-? \ d + (\. \ d +)?"); public boolean isNumeric (String strNum) {if (strNum == null) {return false; } návratový vzor.matcher (strNum) .matches (); }

Pozrime sa teraz na niektoré tvrdenia týkajúce sa vyššie uvedenej metódy:

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

5. Používanie Apache Commons

V tejto časti si rozoberieme rôzne metódy dostupné v knižnici Apache Commons.

5.1. NumberUtils.isCreatable (reťazec)

NumberUtils od Apache Commons poskytuje statickú metódu NumberUtils.isCreatable (reťazec) ktorá kontroluje či a String je platné číslo Java alebo nie.

Táto metóda akceptuje:

  1. Hexadecimálne čísla začínajúce 0x alebo 0X
  2. Osmičkové čísla začínajúce počiatočnou 0
  3. Vedecký zápis (napríklad 1.05e-10)
  4. Čísla označené kvalifikátorom typu (napríklad 1L alebo 2.2d)

Ak je dodaný reťazec nulový alebo prázdny / prázdny, potom sa to nepovažuje za číslo a metóda sa vráti nepravdivé.

Spustíme niekoľko testov pomocou tejto metódy:

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")). isFalse (); assertThat (NumberUtils.isCreatable ("09")). isFalse ();

Všimnite si, ako sa nám darí pravda tvrdenia pre hexadecimálne čísla, osmičkové čísla a vedecké zápisy v riadkoch 6, 7 a 8.

Na riadku 14 tiež reťazec “09” vracia nepravdivé pretože predchádzajúci “0” označuje, že ide o osmičkové číslo a “09” nie je platné osmičkové číslo.

Pre každý vstup, ktorý sa vráti pravda s touto metódou môžeme použiť NumberUtils.createNumber (reťazec) čo nám dá platné číslo.

5.2. NumberUtils.isParsable (reťazec)

The NumberUtils.isParsable (reťazec) metóda kontroluje, či je daný String je porovnateľný alebo nie.

Analyzovateľné čísla sú tie, ktoré sa úspešne analyzujú pomocou akejkoľvek metódy analýzy Integer.parseInt (reťazec), Long.parseLong (reťazec), Float.parseFloat (reťazec) alebo Double.parseDouble (reťazec).

Na rozdiel od NumberUtils.isCreatable (), táto metóda nebude akceptovať hexadecimálne čísla, vedecké zápisy alebo reťazce končiace akýmkoľvek kvalifikátorom typu, to znamená „F“, „F“, „d“, „D“, „l“alebo„L“.

Pozrime sa na niekoľko potvrdení:

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 ("")). isFalse (); assertThat (NumberUtils.isParsable ("6.2f")). isFalse (); assertThat (NumberUtils.isParsable ("9.8d")). isFalse (); assertThat (NumberUtils.isParsable ("22L")). isFalse (); assertThat (NumberUtils.isParsable ("0xFF")). isFalse (); assertThat (NumberUtils.isParsable ("2,99e + 8")). isFalse ();

Na linke 4, na rozdiel NumberUtils.isCreatable (), číslo začínajúce reťazcom “0” sa nepovažuje za osmičkové číslo, ale za bežné desatinné číslo, a preto vráti hodnotu true.

Túto metódu môžeme použiť ako náhradu za to, čo sme urobili v sekcii 3, kde sa pokúšame analyzovať číslo a skontrolovať chybu.

5.3. StringUtils.isNumeric (CharSequence)

Metóda StringUtils.isNumeric (CharSequence) prísne kontroluje číslice Unicode. To znamená:

  1. Prijateľné sú akékoľvek číslice z ľubovoľného jazyka, ktoré sú číslicami Unicode
  2. Pretože desatinná čiarka sa nepovažuje za číslicu Unicode, nie je platná
  3. Vedúce znaky (pozitívne alebo negatívne) sú tiež neprijateľné

Pozrime sa teraz na túto metódu v akcii:

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

Upozorňujeme, že vstupné parametre v riadkoch 2 a 3 predstavujú čísla 123 v arabčine, respektíve Devanagari. Pretože ide o platné číslice Unicode, táto metóda sa vráti pravda na nich.

5.4. StringUtils.isNumericSpace (CharSequence)

The StringUtils.isNumericSpace (CharSequence) prísne kontroluje číslice a / alebo medzeru Unicode. Toto je rovnaké ako StringUtils.isNumeric () s jediným rozdielom, že prijíma aj medzery, nielen medzery na začiatku a na konci, ale aj vtedy, ak sú medzi číslami:

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. Referenčné hodnoty

Predtým, ako uzavrieme tento článok, prejdime si niekoľko referenčných výsledkov, ktoré nám pomôžu analyzovať, ktoré z vyššie uvedených metód sú pre náš prípad použitia najlepšie.

6.1. Jednoduchá referenčná hodnota

Najprv zaujmeme jednoduchý prístup. Vyberieme jednu hodnotu reťazca - pre náš test použijeme Celé číslo.MAX_VALUE. Potom bude táto hodnota testovaná na základe všetkých našich implementácií:

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 priem. 20 46,577 ± 1,973 ns / op Benchmarking Benchmarking.usingStringUtils_isNumeric priem. 20 35 885 ± 1 691 ns / op Benchmarking.usingStringUtils_isNumericSpace priem. 20 31 979 ± 1 393 ns / op

Ako vidíme, najnákladnejšie operácie sú regulárne výrazy. Potom je to naše základné riešenie založené na prostredí Java.

Ďalej si všimnite, že operácie využívajúce knižnicu Apache Commons sú zväčša rovnaké.

6.2. Vylepšená referenčná hodnota

Využime rozmanitejšiu sadu testov na získanie reprezentatívnejšieho štandardu:

  • 95 hodnôt je číselných (0-94 a Celé číslo.MAX_VALUE)
  • 3 obsahujú čísla, ale stále sú naformátované - „x0‘, ‘0..005′, a „–11
  • 1 obsahuje iba text
  • 1 je a nulový

Po vykonaní rovnakých testov sa zobrazia výsledky:

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_isParzlivý priemer 20 1589,915 ± 203,0 g / m Benchmarking.usingStringUtils_isNumeric priem. 20 1071,753 ± 8 657 ns / op Benchmarking.usingStringUtils_isNumericSpace priem. 20 1157,722 ± 24,139 ns / op

Najdôležitejším rozdielom je, že dva z našich testov - riešenie regulárnych výrazov a základné riešenie založené na prostredí Java - si vymenili miesta.

Z tohto výsledku sa dozvedáme, že vrhanie a manipulácia s NumberFormatException, ktorý sa vyskytuje iba v 5% prípadov, má pomerne veľký vplyv na celkový výkon. Záverom teda je, že optimálne riešenie závisí od nášho očakávaného vstupu.

Môžeme tiež bezpečne dospieť k záveru, že na dosiahnutie optimálneho výkonu by sme mali použiť metódy z knižnice Commons alebo metódu implementovanú podobne.

7. Záver

V tomto článku sme skúmali rôzne spôsoby, ako zistiť, či a String je číselný alebo nie. Pozreli sme sa na obe riešenia - zabudované metódy a tiež externé knižnice.

Ako vždy, implementáciu všetkých vyššie uvedených príkladov a útržkov kódu vrátane kódu použitého na vykonanie testov nájdete na GitHub.


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