Ellenőrizze, hogy egy karakterlánc numerikus-e a Java-ban

1. Bemutatkozás

Gyakran műtét közben Húrs, meg kell találnunk, hogy a Húr érvényes szám, vagy sem.

Ebben az oktatóanyagban több módszert is feltárunk annak megállapítására, hogy az adott adott-e Húr numerikus, először sima Java, majd reguláris kifejezések és végül külső könyvtárak használatával.

Miután befejeztük a különféle megvalósítások megbeszélését, benchmarkok segítségével képet kapunk arról, hogy mely módszerek az optimálisak.

2. Előfeltételek

Kezdjünk néhány előfeltétellel, mielőtt továbblépnénk a fő tartalomra.

A cikk második részében az Apache Commons külső könyvtárát fogjuk használni, amelynek függőségét hozzáadjuk a könyvtárunkhoz pom.xml:

 org.apache.commons commons-lang3 3.9 

A könyvtár legújabb verziója megtalálható a Maven Central oldalon.

3. A Plain Java használata

Talán a legegyszerűbb és legmegbízhatóbb módszer annak ellenőrzésére, hogy a Húr numerikus vagy nem, a Java beépített metódusainak elemzésével:

  1. Integer.parseInt (karakterlánc)
  2. Float.parseFloat (String)
  3. Double.parseDouble (String)
  4. Long.parseLong (String)
  5. új BigInteger (húr)

Ha ezek a módszerek nem dobnak semmit NumberFormatException, akkor ez azt jelenti, hogy az elemzés sikeres volt, és a Húr numerikus:

public static boolean isNumeric (StrN strNum) {if (strNum == null) {return false; } próbáld ki {double d = Double.parseDouble (strNum); } catch (NumberFormatException nfe) {return false; } return true; }

Lássuk ezt a módszert működés közben:

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

Miénkben isNumeric () módszerrel, csak olyan típusú értékeket ellenőrizünk Kettős, de ez a módszer is módosítható annak ellenőrzésére Egész szám, Úszó, Hosszú és nagy számban bármely korábban elemzett módszerrel.

Ezeket a módszereket a Java karakterlánc-átalakítások cikk is tárgyalja.

4. A reguláris kifejezések használata

Most használjuk a regexet -? \ d + (\. \ d +)? hogy megfeleljen a numerikusnak Húrok amely pozitív vagy negatív egész számból és lebegőből áll.

De ez magától értetődik, hogy határozottan módosíthatjuk ezt a regexet a szabályok széles skálájának azonosítása és kezelése érdekében. Itt fogjuk egyszerűsíteni.

Bontjuk le ezt a regexet, és nézzük meg, hogyan működik:

  • -? - ez a rész azonosítja, hogy az adott szám negatív-e, a kötőjel”Szó szerint keresi a kötőjelet és a„?”Opcionálisként jelöli jelenlétét
  • \ d + - ez egy vagy több számjegyet keres
  • (\. \ d +)? - a regex ezen része az úszószámok azonosítása. Itt egy vagy több számjegyet keresünk, amelyet egy pont követ. A kérdőjel végül azt jelzi, hogy ez a teljes csoport választható

A rendszeres kifejezések nagyon tág témakörök. Rövid áttekintéshez olvassa el oktatóanyagunkat a Java reguláris kifejezések API-járól.

Most hozzunk létre egy módszert a fenti reguláris kifejezés használatával:

privát minta minta = Pattern.compile ("-? \ d + (\. \ d +)?"); nyilvános logikai isNumeric (StrN strNum) {if (strNum == null) {return false; } return minta.matcher (strNum) .matches (); }

Most nézzünk meg néhány állítást a fenti módszerről:

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

5. Az Apache Commons használata

Ebben a részben az Apache Commons könyvtárban elérhető különféle módszereket tárgyaljuk.

5.1. NumberUtils.isCreatable (karakterlánc)

NumberUtils Az Apache Commons statikus módszert nyújt NumberUtils.isCreatable (karakterlánc) amely ellenőrzi, hogy a Húr érvényes Java-szám, vagy sem.

Ez a módszer elfogadja:

  1. A 0x vagy 0X kezdetű hexadecimális számok
  2. 0-val kezdődő oktális számok
  3. Tudományos jelölés (például 1.05e-10)
  4. Típusminősítővel jelölt számok (például 1L vagy 2.2d)

Ha a mellékelt karakterlánc nulla vagy üres / üres, akkor ez nem számít számnak, és a módszer visszatér hamis.

Futtassunk néhány tesztet ezzel a módszerrel:

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

Vegye figyelembe, hogyan járunk igaz állítások a hexadecimális számokra, az oktális számokra és a tudományos jelölésekre a 6., 7. és 8. sorban.

Továbbá a 14. sorban a húr “09” visszatér hamis mert az előző “0” azt jelzi, hogy ez egy oktális szám és “09” nem érvényes oktális szám.

Minden visszatérő bemenetre igaz ezzel a módszerrel használhatjuk NumberUtils.createNumber (karakterlánc) amely megadja az érvényes számot.

5.2. NumberUtils.isParsable (karakterlánc)

A NumberUtils.isParsable (karakterlánc) módszer ellenőrzi, hogy az adott Húr értelmezhető vagy sem.

Az értelmezhető számok azok, amelyeket bármely elemzési módszerrel, például Integer.parseInt (karakterlánc), Long.parseLong (String), Float.parseFloat (String) vagy Double.parseDouble (String).

nem úgy mint NumberUtils.isCreatable (), ez a módszer nem fogad el hexadecimális számokat, tudományos jelöléseket vagy bármilyen típusú minősítővel végződő karakterláncokat, vagyis „F”, „F”, „d”, „D”, „l”vagy„L”.

Nézzünk meg néhány megerősítést:

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

A 4. vonalon, ellentétben NumberUtils.isCreatable (), a karakterlánccal kezdődő szám “0” nem tekinthető oktális számnak, de egy normális tizedes szám, ezért igazra tér vissza.

Használhatjuk ezt a módszert a 3. szakaszban tett lépések helyettesítésére, ahol megpróbálunk elemezni egy számot, és hibát keresünk.

5.3. StringUtils.isNumeric (CharSequence)

A módszer, a metódus StringUtils.isNumeric (CharSequence) szigorúan ellenőrzi az Unicode számjegyeket. Ez azt jelenti, hogy:

  1. Bármely nyelv, amely Unicode számjegy, bármely számjegy elfogadható
  2. Mivel a tizedesjegy nem számít Unicode számjegynek, nem érvényes
  3. A vezető jelek (akár pozitív, akár negatív) szintén nem elfogadhatók

Lássuk most ezt a módszert működés közben:

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

Ne feledje, hogy a 2. és 3. sor bemeneti paraméterei számokat képviselnek 123 arabul, illetve devanagari nyelven. Mivel érvényes Unicode számjegyek, ez a módszer visszatér igaz rajtuk.

5.4. StringUtils.isNumericSpace (CharSequence)

A StringUtils.isNumericSpace (CharSequence) szigorúan ellenőrzi az Unicode számjegyeit és / vagy szóközöket. Ez ugyanaz, mint StringUtils.isNumeric () azzal a különbséggel, hogy a szóközöket is elfogadja, nemcsak a vezető és a záró szóközöket, hanem akkor is, ha számok között vannak:

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. Referenciaértékek

Mielőtt befejeznénk ezt a cikket, menjünk át néhány összehasonlító eredményt, amelyek segítenek elemezni a fent említett módszerek közül a legjobban alkalmazható eseteket.

6.1. Egyszerű benchmark

Először egyszerű megközelítést alkalmazunk. Egy sztring értéket választunk - tesztünkhöz használjuk Egész.MAX_VALUE. Ezután ezt az értéket minden megvalósításunkkal teszteljük:

Benchmark Mode Cnt Score Hibaegységek 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.av opg. Benchmarking.usingStringUtils_isNumeric avgt 20 35.885 ± 1.691 ns / op Benchmarking.usingStringUtils_isNumericSpace avgt 20 31.979 ± 1.393 ns / op

Mint látjuk, a legköltségesebb műveletek a reguláris kifejezések. Ezután következik a Java alapú alapvető megoldásunk.

Ezenkívül vegye figyelembe, hogy az Apache Commons könyvtár használatával végzett műveletek nagyjából megegyeznek.

6.2. Továbbfejlesztett benchmark

Használjunk változatosabb tesztkészletet egy reprezentatívabb referenciaértékhez:

  • A 95 érték numerikus (0-94 és Egész.MAX_VALUE)
  • 3 számokat tartalmaz, de még mindig rosszul vannak formázva - ‘x0‘, ‘0..005′, és–11
  • Az 1. csak szöveget tartalmaz
  • 1 az a nulla

Ugyanezen tesztek végrehajtása után meglátjuk az eredményeket:

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 Benchmarking.usingStringUtils_isNumeric avgt 20 1071,753 ± 8,657 ns / op Benchmarking.usingStringUtils_isNumericSpace avgt 20 1157,722 ± 24,139 ns / op

A legfontosabb különbség az, hogy két tesztünk - a reguláris kifejezések megoldása és az alapvető Java-alapú megoldás - helyekkel kereskedett.

Ebből az eredményből megtudhatjuk, hogy a NumberFormatException, amely csak az esetek 5% -ában fordul elő, viszonylag nagy hatással van az összteljesítményre. Tehát arra a következtetésre jutunk, hogy az optimális megoldás a várt inputunktól függ.

Továbbá nyugodtan megállapíthatjuk, hogy az optimális teljesítmény érdekében a Commons könyvtárból származó módszereket vagy hasonló módon megvalósított módszereket kell használnunk.

7. Következtetés

Ebben a cikkben különböző módokat tártunk fel annak megállapítására, hogy a Húr numerikus vagy nem. Mindkét megoldást megvizsgáltuk - beépített módszereket és külső könyvtárakat is.

Mint mindig, a fentiekben bemutatott összes példa és kódrészlet, beleértve a benchmarkok elvégzéséhez használt kódot is, megtalálható a GitHubon.