Wie würden Sie überprüfen, ob ein String eine Zahl ist, bevor Sie ihn analysieren?
Integer.parseInt()
Mobiltelefonnummern nicht analysiert werden NumberFormatException
.
Wie würden Sie überprüfen, ob ein String eine Zahl ist, bevor Sie ihn analysieren?
Integer.parseInt()
Mobiltelefonnummern nicht analysiert werden NumberFormatException
.
Antworten:
Mit Apache Commons Lang 3.5 und höher: NumberUtils.isCreatable
oder StringUtils.isNumeric
.
Mit Apache Commons Lang 3.4 und darunter: NumberUtils.isNumber
oder StringUtils.isNumeric
.
Sie können auch verwenden, StringUtils.isNumericSpace
was true
für leere Zeichenfolgen zurückgibt und interne Leerzeichen in der Zeichenfolge ignoriert. Eine andere Möglichkeit ist die Verwendung, bei NumberUtils.isParsable
der grundsätzlich überprüft wird, ob die Nummer gemäß Java analysiert werden kann. (Die verknüpften Javadocs enthalten detaillierte Beispiele für jede Methode.)
StringUtils.isNumeric()
wahrscheinlich wäre dies hier nicht angebracht, da nur geprüft wird, ob die Zeichenfolge eine Folge von Ziffern ist. Wäre in Ordnung für die meisten Ints, aber nicht für Zahlen mit Dezimalstellen, Gruppentrennzeichen usw.
StringUtils
unterstützt keine führenden Zeichen, aber Sie sollten überprüfen NumberUtils.isCreatable
, es unterstützt Negative richtig.
Dies erfolgt in der Regel mit einer einfachen benutzerdefinierten Funktion (dh Roll-Your-Own-Funktion "isNumeric").
Etwas wie:
public static boolean isNumeric(String str) {
try {
Double.parseDouble(str);
return true;
} catch(NumberFormatException e){
return false;
}
}
Wenn Sie diese Funktion jedoch häufig aufrufen und erwarten, dass viele der Überprüfungen fehlschlagen, weil sie keine Zahl sind, ist die Leistung dieses Mechanismus nicht besonders gut, da Sie sich darauf verlassen, dass für jeden Fehler Ausnahmen ausgelöst werden. Das ist eine ziemlich teure Operation.
Ein alternativer Ansatz kann darin bestehen, einen regulären Ausdruck zu verwenden, um die Gültigkeit einer Zahl zu überprüfen:
public static boolean isNumeric(String str) {
return str.matches("-?\\d+(\\.\\d+)?"); //match a number with optional '-' and decimal.
}
Seien Sie jedoch vorsichtig mit dem oben genannten RegEx-Mechanismus, da er fehlschlägt, wenn Sie nicht-arabische Ziffern verwenden (dh andere Ziffern als 0 bis 9). Dies liegt daran, dass der "\ d" -Teil des RegEx nur mit [0-9] übereinstimmt und international nicht numerisch bekannt ist. (Vielen Dank an OregonGhost für diesen Hinweis!)
Oder eine andere Alternative ist die Verwendung des in Java integrierten Objekts java.text.NumberFormat, um festzustellen, ob sich die Parserposition nach dem Parsen der Zeichenfolge am Ende der Zeichenfolge befindet. Wenn dies der Fall ist, können wir davon ausgehen, dass die gesamte Zeichenfolge numerisch ist:
public static boolean isNumeric(String str) {
NumberFormat formatter = NumberFormat.getInstance();
ParsePosition pos = new ParsePosition(0);
formatter.parse(str, pos);
return str.length() == pos.getIndex();
}
.
in Ihrer Regex angegebene Wert mit jedem Zeichen übereinstimmt, nicht nur mit dem Dezimaltrennzeichen.
Wenn Sie auf Android sind, sollten Sie verwenden:
android.text.TextUtils.isDigitsOnly(CharSequence str)
halte es einfach . Meist kann jeder "neu programmieren" (das Gleiche).
.
,-
Java 8 Lambda-Ausdrücke.
String someString = "123123";
boolean isNumeric = someString.chars().allMatch( Character::isDigit );
Wie @CraigTP in seiner hervorragenden Antwort erwähnt hatte, habe ich ähnliche Leistungsprobleme bei der Verwendung von Ausnahmen, um zu testen, ob die Zeichenfolge numerisch ist oder nicht. Also spalte ich den String und benutze ihn java.lang.Character.isDigit()
.
public static boolean isNumeric(String str)
{
for (char c : str.toCharArray())
{
if (!Character.isDigit(c)) return false;
}
return true;
}
Nach dem Javadoc , Character.isDigit(char)
wird richtig erkennt nicht-lateinische Ziffern. In Bezug auf die Leistung denke ich, dass eine einfache Anzahl von N Vergleichen, bei denen N die Anzahl der Zeichen in der Zeichenfolge ist, rechnerisch effizienter wäre als ein Regex-Abgleich.
UPDATE: Wie von Jean-François Corbett im Kommentar ausgeführt, würde der obige Code nur positive ganze Zahlen validieren, was den Großteil meines Anwendungsfalls abdeckt. Im Folgenden finden Sie den aktualisierten Code, mit dem Dezimalzahlen gemäß dem in Ihrem System verwendeten Standardgebietsschema korrekt überprüft werden. Dabei wird davon ausgegangen, dass das Dezimaltrennzeichen nur einmal in der Zeichenfolge vorkommt.
public static boolean isStringNumeric( String str )
{
DecimalFormatSymbols currentLocaleSymbols = DecimalFormatSymbols.getInstance();
char localeMinusSign = currentLocaleSymbols.getMinusSign();
if ( !Character.isDigit( str.charAt( 0 ) ) && str.charAt( 0 ) != localeMinusSign ) return false;
boolean isDecimalSeparatorFound = false;
char localeDecimalSeparator = currentLocaleSymbols.getDecimalSeparator();
for ( char c : str.substring( 1 ).toCharArray() )
{
if ( !Character.isDigit( c ) )
{
if ( c == localeDecimalSeparator && !isDecimalSeparatorFound )
{
isDecimalSeparatorFound = true;
continue;
}
return false;
}
}
return true;
}
toCharArray()
wird eine Kopie des Arrays im String-Objekt erstellt, da Strings unveränderlich sind. Wahrscheinlich schneller, um die charAt(int index)
Methode direkt für das String-Objekt zu verwenden.
StringIndexOutOfBoundsException
wenn eine Zeichenfolge mit der Länge 0 übergeben wird. Kann mitif(str.length() == 0) return false;
Die Guava-Bibliothek von Google bietet hierfür eine nützliche Hilfsmethode : Ints.tryParse
. Sie verwenden es wie, Integer.parseInt
aber es gibt zurück, null
anstatt eine Ausnahme auszulösen, wenn die Zeichenfolge nicht auf eine gültige Ganzzahl analysiert wird. Beachten Sie, dass Integer und nicht int zurückgegeben wird. Sie müssen es also zurück in int konvertieren / autoboxen.
Beispiel:
String s1 = "22";
String s2 = "22.2";
Integer oInt1 = Ints.tryParse(s1);
Integer oInt2 = Ints.tryParse(s2);
int i1 = -1;
if (oInt1 != null) {
i1 = oInt1.intValue();
}
int i2 = -1;
if (oInt2 != null) {
i2 = oInt2.intValue();
}
System.out.println(i1); // prints 22
System.out.println(i2); // prints -1
Ab der aktuellen Version - Guava r11 - ist es jedoch immer noch mit @Beta gekennzeichnet.
Ich habe es nicht bewertet. Wenn man sich den Quellcode ansieht, entsteht ein gewisser Aufwand durch viele Überprüfungen Character.digit(string.charAt(idx))
der geistigen Gesundheit , aber am Ende verwenden sie die Antwort von @Ibrahim oben, ähnlich, aber etwas anders. Es gibt keine Ausnahmebehandlung bei der Implementierung.
Verwenden Sie keine Ausnahmen, um Ihre Werte zu überprüfen. Verwenden Sie stattdessen Util-Bibliotheken wie Apache NumberUtils:
NumberUtils.isNumber(myStringValue);
Bearbeiten :
Bitte beachten Sie, dass NumberUtils Ihren Wert als hexadezimal interpretiert, wenn Ihre Zeichenfolge mit einer 0 beginnt.
NumberUtils.isNumber("07") //true
NumberUtils.isNumber("08") //false
Number.isNumber()
.
Number.isNumber()
ab der ersten Version der Antwort vom 24. September 12 um 17:01 Uhr vorhanden war.
Warum drängen alle auf Ausnahme- / Regex-Lösungen?
Ich kann zwar verstehen, dass die meisten Leute mit try / catch gut zurechtkommen, aber wenn Sie es häufig tun möchten, kann es extrem anstrengend sein.
Was ich hier getan habe, war die Verwendung des regulären Ausdrucks, der parseNumber () -Methoden und der Array-Suchmethode, um festzustellen, welche die effizienteste war. Dieses Mal habe ich nur ganzzahlige Zahlen betrachtet.
public static boolean isNumericRegex(String str) {
if (str == null)
return false;
return str.matches("-?\\d+");
}
public static boolean isNumericArray(String str) {
if (str == null)
return false;
char[] data = str.toCharArray();
if (data.length <= 0)
return false;
int index = 0;
if (data[0] == '-' && data.length > 1)
index = 1;
for (; index < data.length; index++) {
if (data[index] < '0' || data[index] > '9') // Character.isDigit() can go here too.
return false;
}
return true;
}
public static boolean isNumericException(String str) {
if (str == null)
return false;
try {
/* int i = */ Integer.parseInt(str);
} catch (NumberFormatException nfe) {
return false;
}
return true;
}
Die Ergebnisse in Geschwindigkeit, die ich bekam, waren:
Done with: for (int i = 0; i < 10000000; i++)...
With only valid numbers ("59815833" and "-59815833"):
Array numeric took 395.808192 ms [39.5808192 ns each]
Regex took 2609.262595 ms [260.9262595 ns each]
Exception numeric took 428.050207 ms [42.8050207 ns each]
// Negative sign
Array numeric took 355.788273 ms [35.5788273 ns each]
Regex took 2746.278466 ms [274.6278466 ns each]
Exception numeric took 518.989902 ms [51.8989902 ns each]
// Single value ("1")
Array numeric took 317.861267 ms [31.7861267 ns each]
Regex took 2505.313201 ms [250.5313201 ns each]
Exception numeric took 239.956955 ms [23.9956955 ns each]
// With Character.isDigit()
Array numeric took 400.734616 ms [40.0734616 ns each]
Regex took 2663.052417 ms [266.3052417 ns each]
Exception numeric took 401.235906 ms [40.1235906 ns each]
With invalid characters ("5981a5833" and "a"):
Array numeric took 343.205793 ms [34.3205793 ns each]
Regex took 2608.739933 ms [260.8739933 ns each]
Exception numeric took 7317.201775 ms [731.7201775 ns each]
// With a single character ("a")
Array numeric took 291.695519 ms [29.1695519 ns each]
Regex took 2287.25378 ms [228.725378 ns each]
Exception numeric took 7095.969481 ms [709.5969481 ns each]
With null:
Array numeric took 214.663834 ms [21.4663834 ns each]
Regex took 201.395992 ms [20.1395992 ns each]
Exception numeric took 233.049327 ms [23.3049327 ns each]
Exception numeric took 6603.669427 ms [660.3669427 ns each] if there is no if/null check
Haftungsausschluss: Ich behaupte nicht, dass diese Methoden zu 100% optimiert sind, sondern nur zur Demonstration der Daten
Ausnahmen wurden nur dann gewonnen, wenn die Zahl 4 Zeichen oder weniger beträgt und jede Zeichenfolge immer eine Zahl ist. In welchem Fall sollte überhaupt ein Scheck ausgestellt werden?
Kurz gesagt, es ist äußerst schmerzhaft, wenn Sie beim Versuch / Fang häufig auf ungültige Zahlen stoßen, was Sinn macht. Eine wichtige Regel, die ich immer befolge, ist, NIEMALS try / catch für den Programmfluss zu verwenden . Dies ist ein Beispiel dafür.
Interessanterweise ist das einfache if char <0 || > 9 war extrem einfach zu schreiben, leicht zu merken (und sollte in mehreren Sprachen funktionieren) und gewinnt fast alle Testszenarien.
Der einzige Nachteil ist, dass Integer.parseInt () möglicherweise Nicht-ASCII-Zahlen verarbeitet, während dies bei der Array-Suchmethode nicht der Fall ist.
Für diejenigen, die sich fragen, warum ich gesagt habe, dass es einfach ist, sich an das Zeichenarray zu erinnern. Wenn Sie wissen, dass es keine negativen Vorzeichen gibt, können Sie leicht mit etwas davonkommen, das sich wie folgt verdichtet:
public static boolean isNumericArray(String str) {
if (str == null)
return false;
for (char c : str.toCharArray())
if (c < '0' || c > '9')
return false;
return true;
Abschließend war ich neugierig auf den Zuweisungsoperator im akzeptierten Beispiel mit allen abgegebenen Stimmen. Hinzufügen in der Zuordnung von
double d = Double.parseDouble(...)
ist nicht nur nutzlos, da Sie den Wert nicht einmal verwenden, sondern verschwendet auch Verarbeitungszeit und erhöht die Laufzeit um einige Nanosekunden (was zu einer Erhöhung der Tests um 100 bis 200 ms führte). Ich kann nicht verstehen, warum das jemand tun würde, da es tatsächlich zusätzliche Arbeit ist, um die Leistung zu reduzieren.
Sie würden denken, das wäre optimiert ... obwohl ich vielleicht den Bytecode überprüfen und sehen sollte, was der Compiler tut. Das erklärt nicht, warum es für mich immer länger war, wenn es irgendwie optimiert ist ... deshalb frage ich mich, was los ist. Als Hinweis: Mit länger meine ich, den Test für 10000000 Iterationen auszuführen und dieses Programm mehrmals (10x +) auszuführen, hat immer gezeigt, dass es langsamer ist.
BEARBEITEN: Ein Test für Character.isDigit () wurde aktualisiert.
public static boolean isNumeric(String str)
{
return str.matches("-?\\d+(.\\d+)?");
}
Der reguläre Ausdruck von CraigTP (siehe oben) führt zu einigen falsch positiven Ergebnissen. ZB "23y4" wird als Zahl gezählt, weil '.' Entspricht einem beliebigen Zeichen, das nicht dem Dezimalpunkt entspricht.
Außerdem wird jede Zahl mit einem führenden '+' abgelehnt.
Eine Alternative, die diese beiden kleinen Probleme vermeidet, ist
public static boolean isNumeric(String str)
{
return str.matches("[+-]?\\d*(\\.\\d+)?");
}
true
für ein einzelnes Plus "+"
oder Minus "-"
und false
für"0."
matches("-?\\d+([.]\\d+)?")
Wir können versuchen, alle Zahlen aus der angegebenen Zeichenfolge durch ("") zu ersetzen, dh ein Leerzeichen. Wenn danach die Länge der Zeichenfolge Null ist, können wir sagen, dass die angegebene Zeichenfolge nur Zahlen enthält. [Wenn Sie diese Antwort hilfreich fanden, ziehen Sie bitte eine Abstimmung in Betracht] Beispiel:
boolean isNumber(String str){
if(str.length() == 0)
return false; //To check if string is empty
if(str.charAt(0) == '-')
str = str.replaceFirst("-","");// for handling -ve numbers
System.out.println(str);
str = str.replaceFirst("\\.",""); //to check if it contains more than one decimal points
if(str.length() == 0)
return false; // to check if it is empty string after removing -ve sign and decimal point
System.out.println(str);
return str.replaceAll("[0-9]","").length() == 0;
}
""
ist eine Nummer aber "3.14"
und "-1"
nicht?
Sie können verwenden NumberFormat#parse
:
try
{
NumberFormat.getInstance().parse(value);
}
catch(ParseException e)
{
// Not a number.
}
value
.
Wenn Sie Java verwenden, um eine Android-App zu entwickeln, können Sie die Funktion TextUtils.isDigitsOnly verwenden.
Hier war meine Antwort auf das Problem.
Eine Catch-All-Convenience-Methode, mit der Sie einen beliebigen String mit einem beliebigen Parsertyp analysieren können : isParsable(Object parser, String str)
. Der Parser kann ein Class
oder ein sein object
. Auf diese Weise können Sie auch benutzerdefinierte Parser verwenden, die Sie geschrieben haben und die für jedes Szenario funktionieren sollten, z.
isParsable(Integer.class, "11");
isParsable(Double.class, "11.11");
Object dateFormater = new java.text.SimpleDateFormat("yyyy.MM.dd G 'at' HH:mm:ss z");
isParsable(dateFormater, "2001.07.04 AD at 12:08:56 PDT");
Hier ist mein Code mit Methodenbeschreibungen.
import java.lang.reflect.*;
/**
* METHOD: isParsable<p><p>
*
* This method will look through the methods of the specified <code>from</code> parameter
* looking for a public method name starting with "parse" which has only one String
* parameter.<p>
*
* The <code>parser</code> parameter can be a class or an instantiated object, eg:
* <code>Integer.class</code> or <code>new Integer(1)</code>. If you use a
* <code>Class</code> type then only static methods are considered.<p>
*
* When looping through potential methods, it first looks at the <code>Class</code> associated
* with the <code>parser</code> parameter, then looks through the methods of the parent's class
* followed by subsequent ancestors, using the first method that matches the criteria specified
* above.<p>
*
* This method will hide any normal parse exceptions, but throws any exceptions due to
* programmatic errors, eg: NullPointerExceptions, etc. If you specify a <code>parser</code>
* parameter which has no matching parse methods, a NoSuchMethodException will be thrown
* embedded within a RuntimeException.<p><p>
*
* Example:<br>
* <code>isParsable(Boolean.class, "true");<br>
* isParsable(Integer.class, "11");<br>
* isParsable(Double.class, "11.11");<br>
* Object dateFormater = new java.text.SimpleDateFormat("yyyy.MM.dd G 'at' HH:mm:ss z");<br>
* isParsable(dateFormater, "2001.07.04 AD at 12:08:56 PDT");<br></code>
* <p>
*
* @param parser The Class type or instantiated Object to find a parse method in.
* @param str The String you want to parse
*
* @return true if a parse method was found and completed without exception
* @throws java.lang.NoSuchMethodException If no such method is accessible
*/
public static boolean isParsable(Object parser, String str) {
Class theClass = (parser instanceof Class? (Class)parser: parser.getClass());
boolean staticOnly = (parser == theClass), foundAtLeastOne = false;
Method[] methods = theClass.getMethods();
// Loop over methods
for (int index = 0; index < methods.length; index++) {
Method method = methods[index];
// If method starts with parse, is public and has one String parameter.
// If the parser parameter was a Class, then also ensure the method is static.
if(method.getName().startsWith("parse") &&
(!staticOnly || Modifier.isStatic(method.getModifiers())) &&
Modifier.isPublic(method.getModifiers()) &&
method.getGenericParameterTypes().length == 1 &&
method.getGenericParameterTypes()[0] == String.class)
{
try {
foundAtLeastOne = true;
method.invoke(parser, str);
return true; // Successfully parsed without exception
} catch (Exception exception) {
// If invoke problem, try a different method
/*if(!(exception instanceof IllegalArgumentException) &&
!(exception instanceof IllegalAccessException) &&
!(exception instanceof InvocationTargetException))
continue; // Look for other parse methods*/
// Parse method refuses to parse, look for another different method
continue; // Look for other parse methods
}
}
}
// No more accessible parse method could be found.
if(foundAtLeastOne) return false;
else throw new RuntimeException(new NoSuchMethodException());
}
/**
* METHOD: willParse<p><p>
*
* A convienence method which calls the isParseable method, but does not throw any exceptions
* which could be thrown through programatic errors.<p>
*
* Use of {@link #isParseable(Object, String) isParseable} is recommended for use so programatic
* errors can be caught in development, unless the value of the <code>parser</code> parameter is
* unpredictable, or normal programtic exceptions should be ignored.<p>
*
* See {@link #isParseable(Object, String) isParseable} for full description of method
* usability.<p>
*
* @param parser The Class type or instantiated Object to find a parse method in.
* @param str The String you want to parse
*
* @return true if a parse method was found and completed without exception
* @see #isParseable(Object, String) for full description of method usability
*/
public static boolean willParse(Object parser, String str) {
try {
return isParsable(parser, str);
} catch(Throwable exception) {
return false;
}
}
Ein leistungsfähiger Ansatz, der das Fangen von Versuchen vermeidet und mit negativen Zahlen und wissenschaftlicher Notation umgeht.
Pattern PATTERN = Pattern.compile( "^(-?0|-?[1-9]\\d*)(\\.\\d+)?(E\\d+)?$" );
public static boolean isNumeric( String value )
{
return value != null && PATTERN.matcher( value ).matches();
}
Hier ist meine Klasse, um zu überprüfen, ob eine Zeichenfolge numerisch ist. Es werden auch numerische Zeichenfolgen korrigiert:
Bitte schön...
public class NumUtils {
/**
* Transforms a string to an integer. If no numerical chars returns a String "0".
*
* @param str
* @return retStr
*/
static String makeToInteger(String str) {
String s = str;
double d;
d = Double.parseDouble(makeToDouble(s));
int i = (int) (d + 0.5D);
String retStr = String.valueOf(i);
System.out.printf(retStr + " ");
return retStr;
}
/**
* Transforms a string to an double. If no numerical chars returns a String "0".
*
* @param str
* @return retStr
*/
static String makeToDouble(String str) {
Boolean dotWasFound = false;
String orgStr = str;
String retStr;
int firstDotPos = 0;
Boolean negative = false;
//check if str is null
if(str.length()==0){
str="0";
}
//check if first sign is "-"
if (str.charAt(0) == '-') {
negative = true;
}
//check if str containg any number or else set the string to '0'
if (!str.matches(".*\\d+.*")) {
str = "0";
}
//Replace ',' with '.' (for some european users who use the ',' as decimal separator)
str = str.replaceAll(",", ".");
str = str.replaceAll("[^\\d.]", "");
//Removes the any second dots
for (int i_char = 0; i_char < str.length(); i_char++) {
if (str.charAt(i_char) == '.') {
dotWasFound = true;
firstDotPos = i_char;
break;
}
}
if (dotWasFound) {
String befDot = str.substring(0, firstDotPos + 1);
String aftDot = str.substring(firstDotPos + 1, str.length());
aftDot = aftDot.replaceAll("\\.", "");
str = befDot + aftDot;
}
//Removes zeros from the begining
double uglyMethod = Double.parseDouble(str);
str = String.valueOf(uglyMethod);
//Removes the .0
str = str.replaceAll("([0-9])\\.0+([^0-9]|$)", "$1$2");
retStr = str;
if (negative) {
retStr = "-"+retStr;
}
return retStr;
}
static boolean isNumeric(String str) {
try {
double d = Double.parseDouble(str);
} catch (NumberFormatException nfe) {
return false;
}
return true;
}
}
Regex-Matching
Hier ist ein weiteres Beispiel für ein aktualisiertes "CraigTP" -Regex-Matching mit mehr Validierungen.
public static boolean isNumeric(String str)
{
return str.matches("^(?:(?:\\-{1})?\\d+(?:\\.{1}\\d+)?)$");
}
Regex-Test
1 -- **VALID**
1. -- INVALID
1.. -- INVALID
1.1 -- **VALID**
1.1.1 -- INVALID
-1 -- **VALID**
--1 -- INVALID
-1. -- INVALID
-1.1 -- **VALID**
-1.1.1 -- INVALID
Ausnahmen sind teuer, aber in diesem Fall dauert der RegEx viel länger. Der folgende Code zeigt einen einfachen Test von zwei Funktionen - eine mit Ausnahmen und eine mit Regex. Auf meinem Computer ist die RegEx-Version zehnmal langsamer als die Ausnahme.
import java.util.Date;
public class IsNumeric {
public static boolean isNumericOne(String s) {
return s.matches("-?\\d+(\\.\\d+)?"); //match a number with optional '-' and decimal.
}
public static boolean isNumericTwo(String s) {
try {
Double.parseDouble(s);
return true;
} catch (Exception e) {
return false;
}
}
public static void main(String [] args) {
String test = "12345.F";
long before = new Date().getTime();
for(int x=0;x<1000000;++x) {
//isNumericTwo(test);
isNumericOne(test);
}
long after = new Date().getTime();
System.out.println(after-before);
}
}
// Bitte überprüfen Sie den folgenden Code
public static boolean isDigitsOnly(CharSequence str) {
final int len = str.length();
for (int i = 0; i < len; i++) {
if (!Character.isDigit(str.charAt(i))) {
return false;
}
}
return true;
}
// only int
public static boolean isNumber(int num)
{
return (num >= 48 && c <= 57); // 0 - 9
}
// is type of number including . - e E
public static boolean isNumber(String s)
{
boolean isNumber = true;
for(int i = 0; i < s.length() && isNumber; i++)
{
char c = s.charAt(i);
isNumber = isNumber & (
(c >= '0' && c <= '9') || (c == '.') || (c == 'e') || (c == 'E') || (c == '')
);
}
return isInteger;
}
// is type of number
public static boolean isInteger(String s)
{
boolean isInteger = true;
for(int i = 0; i < s.length() && isInteger; i++)
{
char c = s.charAt(i);
isInteger = isInteger & ((c >= '0' && c <= '9'));
}
return isInteger;
}
public static boolean isNumeric(String s)
{
try
{
Double.parseDouble(s);
return true;
}
catch (Exception e)
{
return false;
}
}
Dies ist ein einfaches Beispiel für diese Prüfung:
public static boolean isNumericString(String input) {
boolean result = false;
if(input != null && input.length() > 0) {
char[] charArray = input.toCharArray();
for(char c : charArray) {
if(c >= '0' && c <= '9') {
// it is a digit
result = true;
} else {
result = false;
break;
}
}
}
return result;
}
Sie können das Objekt java.util.Scanner verwenden.
public static boolean isNumeric(String inputData) {
Scanner sc = new Scanner(inputData);
return sc.hasNextInt();
}
Ich habe die Lösung von CraigTP so geändert, dass auch die wissenschaftliche Notation sowie Punkt und Komma als Dezimaltrennzeichen akzeptiert werden
^-?\d+([,\.]\d+)?([eE]-?\d+)?$
Beispiel
var re = new RegExp("^-?\d+([,\.]\d+)?([eE]-?\d+)?$");
re.test("-6546"); // true
re.test("-6546355e-4456"); // true
re.test("-6546.355e-4456"); // true, though debatable
re.test("-6546.35.5e-4456"); // false
re.test("-6546.35.5e-4456.6"); // false
Deshalb mag ich den Try * -Ansatz in .NET. Zusätzlich zu der traditionellen Parse-Methode, die der Java-Methode ähnelt, gibt es auch eine TryParse-Methode. Ich bin nicht gut in der Java-Syntax (out-Parameter?), Behandeln Sie daher Folgendes als eine Art Pseudocode. Es sollte das Konzept jedoch klar machen.
boolean parseInteger(String s, out int number)
{
try {
number = Integer.parseInt(myString);
return true;
} catch(NumberFormatException e) {
return false;
}
}
Verwendungszweck:
int num;
if (parseInteger("23", out num)) {
// Do something with num.
}
Analysieren Sie es (dh mit Integer#parseInt
) und fangen Sie einfach die Ausnahme ab. =)
Zur Verdeutlichung: Die Funktion parseInt prüft, ob sie die Nummer auf jeden Fall (offensichtlich) analysieren kann, und wenn Sie sie trotzdem analysieren möchten, werden Sie keinen Leistungseinbruch erleiden, wenn Sie die Analyse tatsächlich durchführen.
Wenn Sie es nicht analysieren möchten (oder sehr, sehr selten analysieren möchten), möchten Sie es natürlich natürlich anders machen.
Sie können NumberUtils.isCreatable () von Apache Commons Lang verwenden .
Da NumberUtils.isNumber in 4.0 veraltet ist, verwenden Sie stattdessen NumberUtils.isCreatable ().
Java 8 Stream, Lambda-Ausdruck, funktionale Schnittstelle
Alle behandelten Fälle ( Zeichenfolge null, Zeichenfolge leer usw. )
String someString = null; // something="", something="123abc", something="123123"
boolean isNumeric = Stream.of(someString)
.filter(s -> s != null && !s.isEmpty())
.filter(Pattern.compile("\\D").asPredicate().negate())
.mapToLong(Long::valueOf)
.boxed()
.findAny()
.isPresent();
Ich habe einige Bedingungen dargestellt, um Zahlen und Dezimalstellen ohne Verwendung einer API zu überprüfen.
Überprüfen Sie die 1-stellige Nummer der Fixlänge
Character.isDigit(char)
Überprüfen Sie die Nummer der festen Länge (Angenommen, die Länge beträgt 6).
String number = "132452";
if(number.matches("([0-9]{6})"))
System.out.println("6 digits number identified");
Überprüfen Sie die Anzahl der unterschiedlichen Längen zwischen (Nehmen Sie eine Länge von 4 bis 6 an).
// {n,m} n <= length <= m
String number = "132452";
if(number.matches("([0-9]{4,6})"))
System.out.println("Number Identified between 4 to 6 length");
String number = "132";
if(!number.matches("([0-9]{4,6})"))
System.out.println("Number not in length range or different format");
Überprüfen Sie die Dezimalzahl für die unterschiedliche Länge zwischen (Annahme einer Länge von 4 bis 7).
// It will not count the '.' (Period) in length
String decimal = "132.45";
if(decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))
System.out.println("Numbers Identified between 4 to 7");
String decimal = "1.12";
if(decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))
System.out.println("Numbers Identified between 4 to 7");
String decimal = "1234";
if(decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))
System.out.println("Numbers Identified between 4 to 7");
String decimal = "-10.123";
if(decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))
System.out.println("Numbers Identified between 4 to 7");
String decimal = "123..4";
if(!decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))
System.out.println("Decimal not in range or different format");
String decimal = "132";
if(!decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))
System.out.println("Decimal not in range or different format");
String decimal = "1.1";
if(!decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))
System.out.println("Decimal not in range or different format");
Hoffe, es wird vielen helfen.
Basierend auf anderen Antworten habe ich meine eigenen geschrieben und es werden keine Muster oder Parsing mit Ausnahmeprüfung verwendet.
Es wird auf maximal ein Minuszeichen und auf maximal einen Dezimalpunkt geprüft.
Hier einige Beispiele und deren Ergebnisse:
"1", "-1", "-1,5" und "-1,556" geben true zurück
"1..5", "1A.5", "1.5D", "-" und "--1" geben false zurück
Hinweis: Bei Bedarf können Sie dies ändern, um einen Locale-Parameter zu akzeptieren und diesen an die DecimalFormatSymbols.getInstance () -Aufrufe zu übergeben, um ein bestimmtes Gebietsschema anstelle des aktuellen zu verwenden.
public static boolean isNumeric(final String input) {
//Check for null or blank string
if(input == null || input.isBlank()) return false;
//Retrieve the minus sign and decimal separator characters from the current Locale
final var localeMinusSign = DecimalFormatSymbols.getInstance().getMinusSign();
final var localeDecimalSeparator = DecimalFormatSymbols.getInstance().getDecimalSeparator();
//Check if first character is a minus sign
final var isNegative = input.charAt(0) == localeMinusSign;
//Check if string is not just a minus sign
if (isNegative && input.length() == 1) return false;
var isDecimalSeparatorFound = false;
//If the string has a minus sign ignore the first character
final var startCharIndex = isNegative ? 1 : 0;
//Check if each character is a number or a decimal separator
//and make sure string only has a maximum of one decimal separator
for (var i = startCharIndex; i < input.length(); i++) {
if(!Character.isDigit(input.charAt(i))) {
if(input.charAt(i) == localeDecimalSeparator && !isDecimalSeparatorFound) {
isDecimalSeparatorFound = true;
} else return false;
}
}
return true;
}
Hier sind zwei Methoden, die funktionieren könnten. (Ohne Ausnahmen zu verwenden). Hinweis: Java ist standardmäßig ein Pass-by-Wert, und der Wert eines Strings ist die Adresse der Objektdaten des Strings. Also, wenn du es tust
stringNumber = stringNumber.replaceAll(" ", "");
Sie haben den Eingabewert so geändert, dass keine Leerzeichen mehr vorhanden sind. Sie können diese Zeile entfernen, wenn Sie möchten.
private boolean isValidStringNumber(String stringNumber)
{
if(stringNumber.isEmpty())
{
return false;
}
stringNumber = stringNumber.replaceAll(" ", "");
char [] charNumber = stringNumber.toCharArray();
for(int i =0 ; i<charNumber.length ;i++)
{
if(!Character.isDigit(charNumber[i]))
{
return false;
}
}
return true;
}
Hier ist eine andere Methode für den Fall, dass Sie Floats zulassen möchten. Diese Methode erlaubt angeblich, dass Zahlen in der Form 1.123.123.123.123.123.123 übergeben. Ich habe es gerade gemacht, und ich denke, es müssen weitere Tests durchgeführt werden, um sicherzustellen, dass es funktioniert.
private boolean isValidStringTrueNumber(String stringNumber)
{
if(stringNumber.isEmpty())
{
return false;
}
stringNumber = stringNumber.replaceAll(" ", "");
int countOfDecimalPoint = 0;
boolean decimalPointPassed = false;
boolean commaFound = false;
int countOfDigitsBeforeDecimalPoint = 0;
int countOfDigitsAfterDecimalPoint =0 ;
int commaCounter=0;
int countOfDigitsBeforeFirstComma = 0;
char [] charNumber = stringNumber.toCharArray();
for(int i =0 ; i<charNumber.length ;i++)
{
if((commaCounter>3)||(commaCounter<0))
{
return false;
}
if(!Character.isDigit(charNumber[i]))//Char is not a digit.
{
if(charNumber[i]==',')
{
if(decimalPointPassed)
{
return false;
}
commaFound = true;
//check that next three chars are only digits.
commaCounter +=3;
}
else if(charNumber[i]=='.')
{
decimalPointPassed = true;
countOfDecimalPoint++;
}
else
{
return false;
}
}
else //Char is a digit.
{
if ((commaCounter>=0)&&(commaFound))
{
if(!decimalPointPassed)
{
commaCounter--;
}
}
if(!commaFound)
{
countOfDigitsBeforeFirstComma++;
}
if(!decimalPointPassed)
{
countOfDigitsBeforeDecimalPoint++;
}
else
{
countOfDigitsAfterDecimalPoint++;
}
}
}
if((commaFound)&&(countOfDigitsBeforeFirstComma>3))
{
return false;
}
if(countOfDecimalPoint>1)
{
return false;
}
if((decimalPointPassed)&&((countOfDigitsBeforeDecimalPoint==0)||(countOfDigitsAfterDecimalPoint==0)))
{
return false;
}
return true;
}