文字列を解析する前に、文字列が数値かどうかをどのように確認しますか
Apache Commons Lang 3.5以上の場合: NumberUtils.isCreatable
または StringUtils.isNumeric
。
Apache Commons Lang 3.4以下の場合: NumberUtils.isNumber
または StringUtils.isNumeric
。
空の文字列にはtrue
を返し、文字列の内部スペースを無視する StringUtils.isNumericSpace
を使用することもできます。もう一つの方法は StringUtils.isParsable
を使うことです。これは基本的に番号がJavaによって解析可能であることをチェックします。 (リンクされたjavadocには、各メソッドの詳細な例が含まれています。)
これは一般的に単純なユーザー定義関数(つまりRoll-your-own "isNumeric"関数)で行われます。
何かのようなもの:
public static boolean isNumeric(String str) {
try {
Double.parseDouble(str);
return true;
} catch(NumberFormatException e){
return false;
}
}
ただし、この関数を頻繁に呼び出していて、数値ではないために多くのチェックが失敗すると予想される場合は、失敗ごとにスローされる例外に依存しているため、このメカニズムのパフォーマンスは良くありませんこれはかなり高価な操作です。
別の方法としては、正規表現を使って数字であることの妥当性をチェックすることが考えられます。
public static boolean isNumeric(String str) {
return str.matches("-?\\d+(\\.\\d+)?"); //match a number with optional '-' and decimal.
}
ただし、上記のRegExメカニズムには注意してください。アラビア語以外の数字(0から9以外の数字)を使用している場合は失敗します。これは、正規表現の "\ d"部分は[0-9]のみに一致し、事実上国際的に数値を認識できないためです。 (これを指摘してくれたOregonGhostに感謝!)
あるいは、文字列を解析した後、パーサーの位置が文字列の末尾にあるかどうかを確認するために、Javaの組み込みJava.text.NumberFormatオブジェクトを使用することもできます。もしそうなら、文字列全体が数値であると仮定することができます。
public static boolean isNumeric(String str) {
NumberFormat formatter = NumberFormat.getInstance();
ParsePosition pos = new ParsePosition(0);
formatter.parse(str, pos);
return str.length() == pos.getIndex();
}
あなたがAndroid上にいるなら、あなたはそれを使うべきです
Android.text.TextUtils.isDigitsOnly(CharSequence str)
複雑にしないでおく。ほとんどの人は「再プログラム」できます(同じこと)。
@CraigTPが優れた回答で述べたように、文字列が数値であるかどうかをテストするためにExceptionsを使用することについても、同様のパフォーマンス上の懸念があります。そのため、文字列を分割してJava.lang.Character.isDigit()
を使います。
public static boolean isNumeric(String str)
{
for (char c : str.toCharArray())
{
if (!Character.isDigit(c)) return false;
}
return true;
}
Javadoc によると、Character.isDigit(char)
はラテン語以外の数字を正しく認識します。パフォーマンス面では、単純なN回の比較(Nは文字列内の文字数)が正規表現のマッチングよりも計算効率が高いと思います。
更新:コメントでJean-FrançoisCorbettが指摘したように、上記のコードは正の整数のみを検証します。これは私のユースケースの大部分をカバーします。以下は、システムで使用されているデフォルトのロケールに従って10進数を正しく検証するための更新されたコードです。
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;
}
Java 8のラムダ式。
String someString = "123123";
boolean isNumeric = someString.chars().allMatch( Character::isDigit );
GoogleのGuavaライブラリはこれを行うためのNiceヘルパーメソッドを提供します:Ints.tryParse
。 Integer.parseInt
のように使用しますが、文字列が有効な整数に解析されない場合は例外をスローするのではなくnull
を返します。 intではなくIntegerが返されるため、/ autoboxをintに戻す必要があります。
例:
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
ただし、現在のリリース(Guava r11)からはまだ@Betaとマークされています。
ベンチマークしていません。ソースコードを見ると、たくさんの健全性チェックからいくらかのオーバーヘッドがありますが、結局のところ、それらはCharacter.digit(string.charAt(idx))
を使います。実装のカバーの下に例外処理のオーバーヘッドはありません。
値を検証するために例外を使用しないでください。 Apache NumberUtilsのようにUtil libsを使用します。
NumberUtils.isNumber(myStringValue);
編集 :
文字列が0で始まる場合、NumberUtilsは値を16進数として解釈します。
NumberUtils.isNumber("07") //true
NumberUtils.isNumber("08") //false
なぜみんなが例外/正規表現の解決策を推し進めているのですか?
私はほとんどの人がtry/catchを使っても大丈夫だと理解することができますが、あなたが頻繁にそれをしたいのであれば...それは非常に課税になることができます。
ここでやったことは、正規表現、parseNumber()メソッド、そして配列検索メソッドを使ってどれが最も効率的かを確認することでした。今回は整数のみを見ました。
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;
}
私が得たスピードの結果は次のとおりです。
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
免責事項:私はこれらの方法が100%最適化されていると主張しているのではなく、データのデモンストレーションのためだけのものです
数が4文字以下で、すべての文字列が always a number ...の場合に限り、例外が発生します。
つまり、try/catchを使って無効な数値に頻繁に遭遇すると、非常に面倒な作業になります。私が常に従う重要な規則は プログラムフローのためにtry/catchを決して使わないこと です。これはその理由の一例です。
興味深いことに、もしchar <0 ||なら単純> 9は非常に簡単に書くことができ、覚えやすく(そして複数の言語で動作するはずです)、ほとんどすべてのテストシナリオに勝ちます。
唯一の欠点は、Integer.parseInt()がASCII以外の数を処理する可能性があるのではないかと推測しているのに対し、配列検索メソッドは処理しないことです。
なぜ私が文字配列1を覚えるのが簡単であると言ったのか疑問に思う人たちのために、もしあなたが負の兆候がないのを知っているなら、あなたは簡単にこれとして要約された何かで逃げることができる
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;
最後に、最後の注意として、受け入れられた例の代入演算子について、投票がすべて上がったことに興味がありました。の割り当てに追加
double d = Double.parseDouble(...)
この値を使用しないため無駄になるだけでなく、処理時間が無駄になり、ランタイムが数ナノ秒増加しました(テストでは100-200ミリ秒の増加につながりました)。それは実際にはパフォーマンスを低下させるための余分な作業であるため、私は誰もがなぜそうするのか分からない。
バイトコードをチェックして、コンパイラが何をしているのかを確認する必要があるかもしれません。それはなぜそれがどういうわけか最適化されている場合でも、なぜそれが私にとって常に長いと表示されたのかを説明していません...したがって、何が起こっているのだろうか。注:長めに言うと、10000000回の繰り返しでテストを実行し、そのプログラムを複数回(10x +)実行すると常に遅くなることがわかりました。
編集:Character.isDigit()のテストを更新しました。
public static boolean isNumeric(String str)
{
return str.matches("-?\\d+(.\\d+)?");
}
CraigTPの正規表現(上図)はいくつかの誤検知を引き起こします。例えば。 「23y4」は「。」なので数として数えられます。小数点以外の任意の文字と一致します。
また、先頭に「+」を付けて数字を拒否します。
これら2つの小さな問題を回避する代替策は
public static boolean isNumeric(String str)
{
return str.matches("[+-]?\\d*(\\.\\d+)?");
}
NumberFormat#parse
を使用できます。
try
{
NumberFormat.getInstance().parse(value);
}
catch(ParseException e)
{
// Not a number.
}
Javaを使用してAndroidアプリを開発する場合は、 TextUtils.isDigitsOnly 関数を使用できます。
与えられた文字列からすべての数を( "")すなわち空白に置き換えてみることができます。その後、文字列の長さがゼロであれば、与えられた文字列は数字だけを含むと言えます。 [この回答が参考になった場合は、投票してください。] 例:
boolean isNumber(String str){
return str.replaceAll("[0-9]","").length() == 0;
}
これが私の問題に対する答えです。
あなたがあらゆるタイプのパーサであらゆる文字列を解析するために使用できるキャッチオール便利メソッド:isParsable(Object parser, String str)
。パーサーはClass
でもobject
でも構いません。これはまたあなたが書いたカスタムパーサーを使うことを可能にし、どんなシナリオでもうまくいくはずです。例えば:
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");
これが私のコードのメソッドの説明です。
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;
}
}
ASCIIの数字のみを含む正の10進整数のみを照合するには、次のようにします。
public static boolean isNumeric(String maybeNumeric) {
return maybeNumeric != null && maybeNumeric.matches("[0-9]+");
}
正規表現マッチング
これは、より多くの検証を使ってアップグレードされた "CraigTP"正規表現マッチングの別の例です。
public static boolean isNumeric(String str)
{
return str.matches("^(?:(?:\\-{1})?\\d+(?:\\.{1}\\d+)?)$");
}
正規表現テスト
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
トライキャッチを回避し、負の数と科学的記数法を処理することでうまく行けるアプローチ.
Pattern PATTERN = Pattern.compile( "^(-?0|-?[1-9]\\d*)(\\.\\d+)?(E\\d+)?$" );
public static boolean isNumeric( String value )
{
return value != null && PATTERN.matcher( value ).matches();
}
例外は高価ですが、この場合、RegExははるかに長くかかります。以下のコードは、2つの関数の単純なテストを示しています。1つは例外を使用し、もう1つは正規表現を使用します。私のマシンではRegExのバージョンは例外よりも10倍遅いです。
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);
}
}
これは文字列が数値かどうかをチェックするための私のクラスです。数値文字列も修正します。
どうぞ...
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;
}
}
//以下のコードを確認してください
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;
}
これはこのチェックの簡単な例です。
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;
}
// 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;
}
}
Java.util.Scannerオブジェクトを使用できます。
public static boolean isNumeric(String inputData) {
Scanner sc = new Scanner(inputData);
return sc.hasNextInt();
}
Apache Commons Lang からNumberUtils.isCreatable()を使用できます。
NumberUtils.isNumberは4.0では推奨されなくなるので、代わりにNumberUtils.isCreatable()を使用してください。
それを(つまり Integer#parseInt
で)解析して、単に例外をキャッチしてください。 =)
明確にするために:parseInt関数は、(明らかに)どんな場合でも数値を解析できるかどうかをチェックします。それでもやはりそれを解析したいのであれば、実際に解析を行ってもパフォーマンスの低下は起こりません。
あなたがそれをパースしたくない(あるいは非常にまれにそれをパースする)のを望まないなら、もちろん違う方法でそれをしたいかもしれません。
だからこそ私は.NETのTry *アプローチが好きです。 Javaのような従来のParseメソッドに加えて、TryParseメソッドもあります。私はJavaのシンタックス(outパラメータ?)が得意ではないので、次のものをある種の擬似コードとして扱ってください。それは概念を明確にするはずです。
boolean parseInteger(String s, out int number)
{
try {
number = Integer.parseInt(myString);
return true;
} catch(NumberFormatException e) {
return false;
}
}
使用法:
int num;
if (parseInteger("23", out num)) {
// Do something with num.
}
科学的な表記法とドットとコンマの両方を小数点記号として使用するようにCraigTPのソリューションを変更しました。
^-?\d+([,\.]\d+)?([eE]-?\d+)?$
例
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
Java 8ストリーム、ラムダ式、機能的インタフェース
処理されたすべてのケース( 文字列null、文字列emptyなど )
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();
文字列に小数が含まれる場合はBigDecimal
を使用できます。
try {
new Java.math.BigInteger(testString);
} catch(NumberFormatException e) {
throw new RuntimeException("Not a valid number");
}
これは、StringがNumberかどうかを確認するための最も速い方法です。
public static boolean isNumber(String str){
int i=0, len=str.length();
boolean a=false,b=false,c=false, d=false;
if(i<len && (str.charAt(i)=='+' || str.charAt(i)=='-')) i++;
while( i<len && isDigit(str.charAt(i)) ){ i++; a=true; }
if(i<len && (str.charAt(i)=='.')) i++;
while( i<len && isDigit(str.charAt(i)) ){ i++; b=true; }
if(i<len && (str.charAt(i)=='e' || str.charAt(i)=='E') && (a || b)){ i++; c=true; }
if(i<len && (str.charAt(i)=='+' || str.charAt(i)=='-') && c) i++;
while( i<len && isDigit(str.charAt(i)) ){ i++; d=true;}
return i==len && (a||b) && (!c || (c && d));
}
static boolean isDigit(char c){
return c=='0' || c=='1' || c=='2' || c=='3' || c=='4' || c=='5' || c=='6' || c=='7' || c=='8' || c=='9';
}
IntStreamを使用したvery long文字列の並列チェック
Java 8では、与えられたstring
のすべての文字が '0'から '9'の範囲内にあるかどうかをテストします。空の文字列が受け入れられることに注意してください。
string.chars().unordered().parallel().allMatch( i -> '0' <= i && '9' >= i )
私が自分で書いた他の答えに基づいて、それはパターンや例外チェックによる解析を使用しません。
最大1つのマイナス記号をチェックし、最大1つの小数点をチェックします。
これがいくつかの例とその結果です。
"1"、 " - 1"、 " - 1.5"、 " - 1.556"はtrueを返します。
"1..5"、 "1A.5"、 "1.5D"、 " - "、 " - 1"はfalseを返します
注:必要に応じて、これを変更してLocaleパラメーターを受け入れ、それをDecimalFormatSymbols.getInstance()呼び出しに渡して現在のロケールではなく特定のLocaleを使用することができます。
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;
}
APIを使用せずに数字と小数をチェックするためのいくつかの条件を説明しました。
チェック長さ1桁の数字をチェック
Character.isDigit(char)
修正の長さ番号を確認してください(長さが6であると想定します)
String number = "132452";
if(number.matches("([0-9]{6})"))
System.out.println("6 digits number identified");
間の可変長数をチェックする(長さ4〜6と仮定)
// {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");
可変長10進数の間の10進数をチェックします(4〜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");
それが多くの人に役立つことを願っています。
次の方法で確認してみてください。
public static boolean isNumeric(String str) {
NumberFormat formatter = NumberFormat.getInstance();
ParsePosition pos = new ParsePosition(0);
formatter.parse(str, pos);
return str.length() == pos.getIndex();
}
それでは、このメソッドを呼び出すなど、非常に長いStringの入力で何が起きたのでしょうか。
System.out.println(isNumeric("94328948243242352525243242524243425452342343948923"));
結果は "true"です、また大きすぎる数です!チェックするために正規表現を使った場合も同じことが起こります!このようにチェックする方法:
public static boolean isNumeric(String str) {
try {
int number = Integer.parseInt(str);
return true;
} catch (Exception e) {
return false;
}
}
そして結果は私が期待したものです!
これはうまくいくかもしれない2つの方法です。 (例外を使用せずに)。注:Javaはデフォルトで値渡し、Stringの値はStringのオブジェクトデータのアドレスです。
stringNumber = stringNumber.replaceAll(" ", "");
入力値をスペースがないように変更しました。必要に応じてその行を削除できます。
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;
}
これはフロートを許可したい場合の別の方法です。この方法では、フォーム内の数字を合格にすることができます。それが機能していることを確認するため。
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;
}
文字列が数値かどうかを確実に判断する唯一の方法は、文字列を解析することです。だから私はただそれを解析するでしょう、そしてそれが数であれば、あなたは無料でintで数を得ます!
これを試して:
public boolean isNumber(String str)
{
short count = 0;
char chc[] = {'0','1','2','3','4','5','6','7','8','9','.','-','+'};
for (char c : str.toCharArray())
{
for (int i = 0;i < chc.length;i++)
{
if( c == chc[i]){
count++;
}
}
}
if (count != str.length() )
return false;
else
return true;
}
正規表現を使用してチェックを行いたい場合は、最終的な静的Patternオブジェクトを作成する必要があります。そうすれば、正規表現は1回コンパイルするだけで済みます。正規表現のコンパイルには、一致を実行するのにかかる時間がかかるため、この予防策を講じることで、メソッドの実行時間を半分に短縮できます。
final static Pattern NUMBER_PATTERN = Pattern.compile("[+-]?\\d*\\.?\\d+");
static boolean isNumber(String input) {
Matcher m = NUMBER_PATTERN.matcher(input);
return m.matches();
}
私は、数字はその中に小数桁数しかない文字列であると仮定します。おそらく最初と最後にではなく1つの小数点以下の+または - 記号と他の文字(カンマ、スペース、他のカウントシステム、ローマ数字、象形文字).
この解決法は簡潔でかなり速いですが、あなたはこのようにすることによって百万回の呼び出しにつき数ミリ秒を剃ることができます
static boolean isNumber(String s) {
final int len = s.length();
if (len == 0) {
return false;
}
int dotCount = 0;
for (int i = 0; i < len; i++) {
char c = s.charAt(i);
if (c < '0' || c > '9') {
if (i == len - 1) {//last character must be digit
return false;
} else if (c == '.') {
if (++dotCount > 1) {
return false;
}
} else if (i != 0 || c != '+' && c != '-') {//+ or - allowed at start
return false;
}
}
}
return true;
}