Skip to main content

static boolan Integer.isInteger(String)

78 replies [Last post]
monika_krug
Offline
Joined: 2004-10-14

I would like to have a method static boolan Integer.isInteger(String) that returns true in the same cases when the parseInt(String) method is successful.

That way, one could write code like this:

String input = "";<br />
do<br />
{<br />
  System.out.print("insert a whole number: ");<br />
  input = bufferedReader.readLine();<br />
} while (!Integer.isInteger(input));<br />
int number = Integer.parseInt(input);
instead of like this:
String input = "";<br />
int number = 0;<br />
boolean error = false;<br />
do<br />
{<br />
  System.out.print("insert a whole number: ");<br />
  input = bufferedReader.readLine();<br />
  error = false;<br />
  try<br />
  {<br />
    number = Integer.parseInt();<br />
  }<br />
  catch(NumberFormatException ex)<br />
  {<br />
    error = true;<br />
  }<br />
} while (error);
I have only ever needed this for ints, but if this method is added, Short.isShort(String), Double.isDouble(String) etc. should be added to the other wrapper classes, too.

Additionally, for the classes that also have a parse*(String, int radix) method, there should also be a is*(String, radix) method (e.g. isInt(String, radix)).

Monika.

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
francismok
Offline
Joined: 2005-05-22

> An API is supposed to put solutions to common
> problems in an openly accessible solution database.
> isInteger (and its primitive relatives) would
> certainly be an improvement to the API.

+ 1
some very common function should be putted in the JDK,
just like Object.equals()
Sometime it is worth to add a new function, just like the String.isBlank() in 1.6/6.0

Integer.isInteger() should add performance overhead as double prasing is needed.

so we can implement like:

//genius
Interger i = Integer.valueOf(N1234);
if (i.isInt) {
//blah blah
}

or

//in a C# way ?!?!
//still genius
//Integer.valueOf() return a static memeber called invaldInteger
Integer i - Integer.valueOf(N1234);
if(!(i == Integer.invaldInteger)){
}

//look much stupid
Integer i = Integer.valurOf(N1234)
if(i != null) {
}

or

//Moron?!?!
Integer i = Integer.valueOf(N1234);
if(!i instanceof InvaldInteger){
}

or

// the old way look much moron, right?!?!
Integer i = null;
try {
i = Integer.valurOf(N1234);
} catch ( NumberFormatException nfe) {
}

I love the first 2 proposals, 1st is simple && 2nd is a Design Pattern!!!

Thanks in Advance!

alexlamsl
Offline
Joined: 2004-09-02

One thing though - that try-catch block for scanning through the array has the best run-time of all.

I think the author is suggesting that using this instead of the for loop construct would be less user-friendly (since for loops are tailor-made for the purpose here)

So it is a compromise between speed and maintainability here - and the fact that such optimization can actually be carry out by the JVM (a pretty much straight forward replacement of a for-loop with this try-catch block) means we should not sacrifice readability here.

But with your argument for having isInteger() though, readablity and maintainability of the Java Language [b]on the whole[/b] would decrease with the introduction of such "friendly" methods, hence the use of the simpler try-catch block is the better choice here.

zander
Offline
Joined: 2003-06-13

> Anyway, I have seen you argue from a performance
> perspective, but never an object oriented
> perspective, on why there shouldn't be an isInteger
> method. What is your object oriented argument?

To do this in an object oriented manner (and without duplicating the parsing code); you would need an API that returns an object which contains the parsed result. That object could then be queries if it is an integer and if it is, another getter could be used to get the actual integer.

Something like this:
[code]
public class PossibleInteger extends Number {
private PossibleInteger() { } // empty private constructor
public PossibleInteger(String integer) throws NumberformatException {
init(integer);
if(!isInteger())
throw new NumberFormatException(bla);
}
private void init(String val) {
// the logic...
}
public boolean isInteger() {
return isAnInteger;
}
public int intValue() {
return intValue;
}
public static PossibleInteger fetchInteger(String val) {
PossibleInteger pi = new PossibleInteger();
pi.init(val);
return pi;
}
}
[/code]

You could add a parseInt and a isInteger method there with easy, I would guess.

This is what I consider good object-oriented design (well, its a [i]very[/i] quick design).
Adding doubles, floats and all the other stuff to this one object is also not really hard to do.

Perhaps you want to code this and submit it in a working order to Sun for further inclusion, I would surely support a design like this.

adeodatus
Offline
Joined: 2005-04-04

You may or may not have any idea how many times someone asks how to check if a String is an Integer. Anyway, it's a lot. The try/catch version, the copy straight from Integer's source version, and the struggle and do it yourself version have doubtless been coded many times.

An API is supposed to put solutions to common problems in an openly accessible solution database. isInteger (and its primitive relatives) would certainly be an improvement to the API.

~Cheers

jwenting
Offline
Joined: 2003-12-02

So make the standard library so that it can read your mind and write your entire application for you...
That way noone will ever make a programming error again.

zander
Offline
Joined: 2003-06-13

> If a program needs the micro-optimization of not
> doing an isInteger before a parseInt, then the
> programer can implement it as a try/catch. That
> doesn't justify not having the method in the API. How
> is an isInteger method a bad programing practice that
> Java must not implement it to not encourage it? If
> such micro-optimizations are the concern of the Java
> language, then concatination of strings with + should
> not be allowed, not to mention auto-boxing.

I'm more inclined to conclude that it is not in the language because not enough attention has been given to this request.

ps. string concatinations in source files are automatically converted to stringbuffers by javac.

yishai
Offline
Joined: 2003-11-16

> > If a program needs the micro-optimization of not
> > doing an isInteger before a parseInt, then the
> > programer can implement it as a try/catch. That
> > doesn't justify not having the method in the API.
> How
> > is an isInteger method a bad programing practice
> that
> > Java must not implement it to not encourage it? If
> > such micro-optimizations are the concern of the
> Java
> > language, then concatination of strings with +
> should
> > not be allowed, not to mention auto-boxing.
>
> I'm more inclined to conclude that it is not in the
> language because not enough attention has been given
> to this request.

So you support the idea or not? I'm confused.

> ps. string concatinations in source files are
> automatically converted to stringbuffers by javac.

[pre]
String s = "Start";
for (Iterator i = collection.iterator(); i.hasNext() ; ) {
s += i.next();
}
[/pre]

StringBuffer conversion isn't going to help you there. If there were no + operator on strings, you would have to make your own StringBuffer, and you would know to make one, outside the for loop. The language would force it on you.

zander
Offline
Joined: 2003-06-13

> So you support the idea or not? I'm confused.

LOL
Did you fail to put together that it is my name next to the lots of messages in this thread telling you that the proposal is not the best solution from an object oriented perspective?

yishai
Offline
Joined: 2003-11-16

> > So you support the idea or not? I'm confused.
>
> LOL
> Did you fail to put together that it is my name next
> to the lots of messages in this thread telling you
> that the proposal is not the best solution from an
> object oriented perspective?

Sure, but the way you wrote that statement, it seemed like you supported the idea. Hence my confusion.

Anyway, I have seen you argue from a performance perspective, but never an object oriented perspective, on why there shouldn't be an isInteger method. What is your object oriented argument?

zander
Offline
Joined: 2003-06-13

oops. duplicate..

Message was edited by: zander

yishai
Offline
Joined: 2003-11-16

> The only reason against my suggestion that I agree
> with is that it would result in the work of parsing
> done twice when it is used for parsing a string that
> is most likely to be an integer anyway.
>
> How could this be avoided?

If a program needs the micro-optimization of not doing an isInteger before a parseInt, then the programer can implement it as a try/catch. That doesn't justify not having the method in the API. How is an isInteger method a bad programing practice that Java must not implement it to not encourage it? If such micro-optimizations are the concern of the Java language, then concatination of strings with + should not be allowed, not to mention auto-boxing.

monika_krug
Offline
Joined: 2004-10-14

You are absolutely right :-)

Monika.

dondi_imperial
Offline
Joined: 2004-11-22

What about this?
[code]StringBuffer stringsum = new StringBuffer();
int intsum = 0;
String i = "";
while((i=getInput())!=null){
if(Integer.isInteger(i)){
intsum+=Integer.parseInt(i);
}else{
stringsum.append(i);
}
}[/code]
Exceptional condition? I don't think so.

Dondi

lucnelis
Offline
Joined: 2004-11-29

If you are concerned with input from a user, then I think the proper way to parse it is using a java.text.NumberFormat. The same NumberFormat instance used for parsing the input from the user should then also be used to format a number to be displayed to the user. Using parseObject(String,ParsePosition) method on a NumberFormat instance returns null when the input is incorrect where the parseposition is set to the position where parsing went wrong. No exceptions are involved and flow-control is even enhanced compared to using a hypothetical method Integer.isInteger(String).

yishai
Offline
Joined: 2003-11-16

> If you have another usage of
> Integer.isInteger(String) that you feel should not be
> done using an exceptions-handling case, please do
> tell us. And if its common enough; you perhaps will
> convince more people that this is needed.

OK, try this one:

A data file (stream, whatever) with 1,000,000 rows, one column. Go through each one and keep those which are Integers (and I mean this formally, I intend to use the non-nullness or non 0 lengthness to assume they are valid Integers later), and blank out all the rest (but don't abort after the first failure, continue on and evaluate the rest of them).

The only way that works out is if you have a try-catch in a tight loop, something to be avoided as a best practice. The only one who can solve that (without each developer rewriting the same code) is the API. java.lang.Integer should hold the logic of what an Integer is, and nothing else.

zander
Offline
Joined: 2003-06-13

> OK, try this one:
>
> A data file (stream, whatever) with 1,000,000 rows,
> one column. Go through each one and keep those which
> are Integers (and I mean this formally, I intend to
> use the non-nullness or non 0 lengthness to assume
> they are valid Integers later), and blank out all the
> rest (but don't abort after the first failure,
> continue on and evaluate the rest of them).

[code]
InputStream is = new FileInputStream("test");
StringBuffer line = new StringBuffer();
while(true) {
int c = is.read();
if(c == -1 || c == '\n') {
try {
Integer.parseInt(line.toString());
/* I'm lazy; i'll use System.out... */
System.out.println(line.toString());
} catch(NumberFormatException e) {
System.out.println("");
}
line = new StringBuffer();
}
else
line.append((char) c);
if(c == -1) break;
}
[/code]

> The only way that works out is if you have a
> try-catch in a tight loop, something to be avoided as
> a best practice.

Why? Try catch as a code-construct does not take any extra time in parsing/running. The only problem you get with the above is if more items are non-integers then there are integers in there since you end up throwing too many exceptions.

> The only one who can solve that
> (without each developer rewriting the same code) is
> the API. java.lang.Integer should hold the logic of
> what an Integer is, and nothing else.

That, I fully agree with.

yishai
Offline
Joined: 2003-11-16

> > The only way that works out is if you have a
> > try-catch in a tight loop, something to be avoided
> as
> > a best practice.

> Why? Try catch as a code-construct does not take any
> extra time in parsing/running.

http://www.javaworld.com/javaworld/javaqa/2001-07/04-qa-0727-try.html

Also, from Effective Java by Bloch, page 170:

"Placing code inside a try-catch block precludes certain optimizations that modern JVM implememtnations might otherwise perform."

> The only problem you
> get with the above is if more items are non-integers
> then there are integers in there since you end up
> throwing too many exceptions.

Chapter 8, item 39 in Effective Java:
[pre]
[b]//Horrible abuse of exceptions. Don't ever do this![/b]
try {
int i=0;
while (true)
a[i++].f();
} catch (ArrayIndexOutOfBoundsException e){
}
[/pre]

This is precisely the coding style you advocate for Integer. And it is a bad practice. To quote from the next page (170) "[b]A well-designed API must not force its client to use exceptions for ordinary control flow.[/b] A class with a "state-dependent" method that can be invoked only under certain unpredictable conditions should generally have a seperate "state-testing" method indicating whether it is appropriate to invoke the first method." And yet, this is precicely what Integer does (admitedly without the actual state).

zander
Offline
Joined: 2003-06-13

> > > The only way that works out is if you have a
> > > try-catch in a tight loop, something to be avoided as
> > > a best practice.
>
> > Why? Try catch as a code-construct does not take any
> > extra time in parsing/running.
>
> http://www.javaworld.com/javaworld/javaqa/2001-07/04-qa-0727-try.html

Please quote what you feel is appropriate; I read:
"Try/catch blocks add a trivial amount of overhead to your programs. In essence, try/catch blocks come free, unless an exception actually throws"

Which is what I said above. Why do you disagree with that? Have you done actual tests supporting your claim?

I have; the time added for try/catch around a Integer.parseint is unmeasurable.

> Also, from Effective Java by Bloch, page 170:
>
> "Placing code inside a try-catch block precludes
> certain optimizations that modern JVM
> implememtnations might otherwise perform."

And this is your argument?

[snip code]
> This is precisely the coding style you advocate for
> Integer.

Look closer; this example is different
a) an exception will always occur, the exception is not an exceptional case in [b]any[/b] usage of this code block. Both not true for the Integer.parseInt
b) the check for bounds is extremely cheap (comparing two numbers); in contrary to the isInteger case (parsing and interpreting a string)

> And it is a bad practice. To quote from the
> next page (170) "[b]A well-designed API must not
> force its client to use exceptions for ordinary
> control flow.[/b]

There are many cases where actually doing the action instead of finding out if it will succeed is preferred. Writing to a file or network are obvious examples. I think you are misinterpreting the advice as a set-in-stone rule.

> A class with a "state-dependent"
> method that can be invoked only under certain
> unpredictable conditions should generally have a
> seperate "state-testing" method indicating whether it
> is appropriate to invoke the first method." And yet,
> this is precicely what Integer does (admitedly
> without the actual state).

Integer.parseInt is a static method, therefor there is no class, and thus no state. This changes the whole game since there is no single boolean to check or whatever; you have to do the actual work to find out if it can be done.

yishai
Offline
Joined: 2003-11-16

> > Why? Try catch as a code-construct does not take any
> > extra time in parsing/running.
>
> http://www.javaworld.com/javaworld/javaqa/2001-07/04-qa-0727-try.html

> Please quote what you feel is appropriate; I read:
> "Try/catch blocks add a trivial amount of overhead to
> your programs. In essence, try/catch blocks come free,
> unless an exception actually throws"

"You should also avoid placing try/catch blocks within a loop. Though trivial once, try/catch blocks can add up when performed many times inside a loop."

> There are many cases where actually doing the action
> instead of finding out if it will succeed is
> preferred. Writing to a file or network are obvious
> examples. I think you are misinterpreting the advice
> as a set-in-stone rule.

Those are both checked exceptions, and for good reason. You cannot know ahead of time. If you made a boolean method to see if you have permission to write some value to a file, that doesn't mean that the file won't get deleted, or the operating system raise some other objection, in the next statement. Having a pre-validation method there doesn't do anything, as the validation cannot be assured to hold.

That doesn't apply to parsing a string, as the programmer is in complete control if he passes to the parseInt the same thing that he passed to isInt.

>
> > A class with a "state-dependent"
> > method that can be invoked only under certain
> > unpredictable conditions should generally have a
> > seperate "state-testing" method indicating whether
> it
> > is appropriate to invoke the first method." And
> yet,
> > this is precicely what Integer does (admitedly
> > without the actual state).
>
> Integer.parseInt is a static method, therefor there
> is no class, and thus no state. This changes the
> whole game since there is no single boolean to check
> or whatever; you have to do the actual work to find
> out if it can be done.

I am starting to see from your other post that the static nature of the parsing is what is bothering you. But I don't understand why. The fact that there is a boolean to check is purely an implementation detail, and not all the concern of anything outside the API. When I call Vector.size() or LinkedList.size() I don't care that their implementations are different, or what they do to figure that out. Similarly with Integer, the isInt is just as good as a parseInt. Integer is the class which proxies for an int, and it has parseInt as a static method because ints are primitive. They could have designed Integer without a parseInt method, and made you do a new Integer(String).intValue() instead. They don't do that for performance reasons (spurious Object creation of the Integer). Same thing here, add an isInt method to complement the parseInt method to avoid the try/catch and exception throwing.

And if your objection is a performance one (you have to parse twice), then not having the isInt method creates irreducible (without getting really ugly, and possibly violating a license agreement) perfomance problems. Having one just creates a potentially slow idiom (checking isInt before parsing isInt), but a very readable idiom, and you already have much bigger potential issues with similar idioms in Java with the + operator on String and auto-boxing. And if you want to avoid the double parsing, you can just catch the exception. So what is the problem?

ulfzibis
Offline
Joined: 2005-02-18

> I think of exceptions, especially runtime exceptions, as this:
>
> "Unchecked exceptions, being the opposite of checked exceptions, indicate that the program is in an unrecoverable state."
>
> Using it for simply boolean flow control is a bad practice, performance-wise, not to mention error prone.

On the other hand, there are examples in the API where [b]exceptional situations[/b] are [u]not handled by Exception[/u] und must be [u]catched by boolean query[/u]:

[i]boolean java.io.File#renameTo(File dest)[/i]

If the renaming fails, no Exception ist thrown. You must test the return value for true.

zander
Offline
Joined: 2003-06-13

> > Exceptions really [b]are all about[/b] flow
> > control; how else can you look at it?

> I think of exceptions, especially runtime exceptions,
> as this:
>
> "Unchecked exceptions, being the opposite of checked
> exceptions, indicate that the program is in an
> unrecoverable state."

While this statement certainly has truth behind it; you miss a very important aspect of the given example. The strings parsed are not hardcoded and thus are user input. Any input coming from keyboard/file/user should never be trusted and thus the premise that a programming error is the one causing the NumberFormatException (due to a programmer not typing a correct number) is false, and basically invalidates the whole reasoning behind the linked blog story.

The usage of an unchecked exception in this case (parseInt) is because the usage of the method would otherwise be annoying and counter-productive. So, as long as you are using trusted strings, you can leave out the try/catch stuff.
Only when you are not absolutely sure your strings will parse (and user input should never be trusted) then you will have to use the try/catch.

This design of API is quite common in Java, and I suggest you look at
http://www.javaworld.com/javaworld/jw-08-2001/jw-0803-exceptions.html

yishai
Offline
Joined: 2003-11-16

> The strings parsed are not hardcoded and
> thus are user input. Any input coming from
> keyboard/file/user should never be trusted and thus
> the premise that a programming error is the one
> causing the NumberFormatException (due to a
> programmer not typing a correct number) is false,
> and basically invalidates the whole reasoning behind
> the linked blog story.

All the more reason to have a method which tells you if it is an Integer (Long, or what-have-you) rather than having the only way be an API which throws a runtime exception.

> The usage of an unchecked exception in this case
> (parseInt) is because the usage of the method would
> otherwise be annoying and counter-productive. So,
> , as long as you are using trusted strings, you can
> leave out the try/catch stuff.
> Only when you are not absolutely sure your strings
> will parse (and user input should never be trusted)
> then you will have to use the try/catch.

I am not arguing that it should be a checked exception. But I do think that any API which throws a runtime exception should go to all reasonable efforts to make it possible for the programmer to avoid the runtime exception ahead of the method call by doing some validation. And if that validation requires logic specific to the API, the API should provide the validating methods to avoid a runtime exception.

> This design of API is quite common in Java, and I
> suggest you look at
> http://www.javaworld.com/javaworld/jw-08-2001/jw-0803-
> exceptions.html

Other than the Number system (parseInt, parseLong, etc.), what other examples of APIs do you have where there is no way to know if a method will succeed without catching an unchecked exception?

zander
Offline
Joined: 2003-06-13

> All the more reason to have a method which tells you
> if it is an Integer (Long, or what-have-you) rather
> than having the only way be an API which throws a
> runtime exception.

Again; thats a personal thing and not in line with common Java APIs.

> Other than the Number system (parseInt, parseLong,
> etc.), what other examples of APIs do you have where
> there is no way to know if a method will succeed
> without catching an unchecked exception?

Vector.get()/Vector.indexOf
all securityManager stuff; ranging from System.getProperties() to File.getAbsolutePath()
UndoManager.undo() (in Swing)

And, naturally things as simple as "a/b" when b is '0'.

Thats just a very small stack that I can think of right now, in fact; its everywhere. So, did you read the linked article? Or do you think thats also incorrect and misguided.

monika_krug
Offline
Joined: 2004-10-14

> Vector.get()/Vector.indexOf
> all securityManager stuff; ranging from
> System.getProperties() to File.getAbsolutePath()
> UndoManager.undo() (in Swing)
>
> And, naturally things as simple as "a/b" when b is
> '0'.

You are giving examples for the opposite of what you are arguing.

Do you do
try
{
[...] vector.get(index);
}
catch(IndexOutOfBoundsException ex)
{
[...]
}
? No, you would usually make sure the index is valid by checking index < vector.size() or by using an iterator.

Do you do
try
{
[...] a/b;
}
catch(ArithmeticException ex)
{
[...]
}
? Certainly not, you would check b != 0 instead.

UndoManager has a boolean canUndo() method.

And security exceptions are different, in my opinion.

Monika.

jwenting
Offline
Joined: 2003-12-02

> > Vector.get()/Vector.indexOf
> > all securityManager stuff; ranging from
> > System.getProperties() to File.getAbsolutePath()
> > UndoManager.undo() (in Swing)
> >
> > And, naturally things as simple as "a/b" when b is
> > '0'.
>
> You are giving examples for the opposite of what you
> are arguing.
>

he's not... He gives examples of unchecked exceptions.

Of course in those cases you would normally do boundary checks, but that's not the point.
It's easy to write your own function to check whether a string does represent a specific numeric format.
Just try to parse it and catch the exception, returning false if an exception is raised... But shouldn't such be a standard function in the classes that do the parsing?

yishai
Offline
Joined: 2003-11-16

> > > Vector.get()/Vector.indexOf
> > > all securityManager stuff; ranging from
> > > System.getProperties() to File.getAbsolutePath()
> > > UndoManager.undo() (in Swing)
> > >
> > > And, naturally things as simple as "a/b" when b
> is
> > > '0'.
> >
> > You are giving examples for the opposite of what
> you
> > are arguing.
> >
>
> he's not... He gives examples of unchecked
> exceptions.
>
> Of course in those cases you would normally do
> boundary checks, but that's not the point.

No, the point is there is no way to do the bounds check with Integer other than catching an exception or rewriting the logic yourself (all of the regex, etc., suggestions).

> It's easy to write your own function to check whether
> a string does represent a specific numeric format.
> Just try to parse it and catch the exception,
> returning false if an exception is raised... But
> shouldn't such be a standard function in the classes
> that do the parsing?

I'm not sure if you are arguing for the proposal or against it. I agree 100% with the statement "But shouldn't such be a standard function in the class[es] that do[es] the parsing?" With the answer that Integer is the class which does the parsing, so that is where it belongs.

No one is arguing that this is not easy to do yourself. But when you do it yourself, you lose two things. 1) There must be a try/catch block going on somewhere, with exception throwing when needed. try/catch in a tight loop is bad practice, and throwing exceptions for simple logical control is a performance drag, if nothing else. 2) Every project is reimplementing this themselves.

If it were in the Java API, you could avoid the try/catch and exception throwing by refactoring the implementation in Integer, and everyone would have a standard way of answering the question of "Is this string an Integer?".

s690716
Offline
Joined: 2004-03-04

It sounds like a first grade programming excercise in Java from a university / university of applied sciences course.

- Reading a whole number from console
- Convert the string into a specific datatype
- ...

The Java API should not replace student excercises...

dog
Offline
Joined: 2003-08-22

No regular expressions are not a good solution. Integer should be the one to know if something is an Integer or not.. after all it has toString() and can parse Strings too.. why should I have to guess the proper regular expression.. let the class encapsulate that logic.
(localization issues left aside for a moment :) )

jwenting
Offline
Joined: 2003-12-02

> No regular expressions are not a good solution.
yes they are. You're dealing with text, and want to know whether that text represents a certain pattern (namely a pattern consisting only of an optional dash ('-') followed by a series of digits ([0-9]*).

> Integer should be the one to know if something is an
> Integer or not.. after all it has toString() and can
No it's not. Integer deals with numbers, not Strings.

> parse Strings too.. why should I have to guess the
> proper regular expression.. let the class encapsulate
> that logic.
I'd venture that the String handling functions in Integer maybe should not be there and NumberFormat should be used instead.

> (localization issues left aside for a moment :) )

Why? Because taking those into consideration your position would become untennable?

dondi_imperial
Offline
Joined: 2004-11-22

> You are missing that doing a check before then
> requires to do the conversion later again for most
> cases, so this is actually slower.

Not sure but I think the exception handling code adds performance overhead as well.

> Only if you don't convert after the check AND expect
> a high percentage to not be numbers (which will then
> throw exceptions) will this be faster.
> Due to this, the exceptions way is more in line with
> Java and causes me to disagree that your way is the
> correct way.

I agree to disagree. :p With the execption handling code:
[code]int num;
try{
num = Integer.parseInt(someString);
}catch(NumberFormatException e){
num = 0;
}[/code]
This reads "try to set num to the value in someString and if for some reason this fails set num to zero". While the proposed code:
[code]int num;
if(Integer.isInteger(someString)) num = Integer.parseInt(someString);
else num = 0;[/code]
or more concise:
[code]int num = (Integer.isInteger(someString))?Integer.parseInt(someString):0;[/code]
This reads if some string is an integer set num to it's integer value otherwise set it to 0.

I think that this makes the intentions of the programmer and what the code is actually doing clearer.

> How do you reason that that is the class where it is
> suppost to be?
> Why should it not equally logical be on Short, or
> Long?
>
> If anything; I'd put it on java.lang.Number

Uhhh, Number.isInteger? Where else would you put isInteger? :D

Dondi

zander
Offline
Joined: 2003-06-13

> With the execption handling code:
> int num;
> try{
> num = Integer.parseInt(someString);
> }catch(NumberFormatException e){
> num = 0;
> }
> This reads "try to set num to the value in someString
> and if for some reason this fails set num to zero".

I see the 'NumberFormatException' and don't read 'some reason this fails' but a much more specific reason, that its not a number.

> While[]:
> int num = (Integer.isInteger(someString))?Integer.parseInt(someString):0;
> This reads if some string is an integer set num to
> it's integer value otherwise set it to 0.

From my POV; this reads exactly the same as the above. Only this code does the parsing twice (one time for the isInteger, and one time for the parseInt) and apparently the only reason you want this is since you are not confortable [b]using[/b] exceptions.

Thats your choice; but you will not be using the language to its full potential if you avoid exceptions, and basically will deliver worse software in the process.

See also:
http://www.javaworld.com/javaworld/javaqa/1999-06/04-exceptions.html

dondi_imperial
Offline
Joined: 2004-11-22

> I see the 'NumberFormatException' and don't read
> 'some reason this fails' but a much more specific
> reason, that its not a number.

Actually, it fails because it is not an INTEGER. Even you are confused :D. In the code I stated it is clear that you are checking for integral values.

> From my POV; this reads exactly the same as the
> above.

That is because you are used to writing and looking at code this way. The point is that the syntax of the isInteger code more closely resembles the semantic of the code (It is almost a direct translation from english).

> Only this code does the parsing twice (one
> time for the isInteger, and one time for the parseInt)

This totally depends on the implementation of isInteger and parseInt.

> and apparently the only reason you want
> this is since you are not confortable [b]using[/b]
> exceptions.

Anyone who has done any work in java should be comfortable enough with exceptions. And they are the correct way to write code when you are dealing with exceptional conditions. But, for example if you are writing code to sum all the numbers in a text file and you know that this text file may contain strings that are not integers. This is not an exceptional condition this is a logical condition.

> That's your choice; but you will not be using the
> language to its full potential if you avoid
> exceptions,

This is not about avoiding exceptions. It is about using them in the correct way. Exceptions have their place in java but, IMHO controlling the flow of a program where a logical condition is more suitable is not one of them.

> and basically will deliver worse software
> in the process.

Everyone knows that in today's software engineering space code readability is just as (or even more) important as efficient code. If you really wanted your code to run as fast as it possibly could you would write it in assembly language (or maybe machine language). But one of the major reasons most of us use java is because we want to write software that is easier to manage.

> See also:
> http://www.javaworld.com/javaworld/javaqa/1999-06/04-e
> xceptions.html

From the article mentioned in the link above:
"Only when the situation is truly exceptional should you use this mechanism, though you may be tempted to throw exceptions simply to take advantage of their control-flow aspects."

Here we are indeed tempted if not forced to use exception handling because it is the only way we have and that in my opinion is a kludge.

Dondi

ulfzibis
Offline
Joined: 2005-02-18

> From the article mentioned in the link above:
> "Only when the situation is truly exceptional should you use this mechanism, though you may be tempted to throw exceptions simply to take advantage of their control-flow aspects."

On the other hand, there are examples in the API where [b]exceptional situations[/b] are [u]not handled by Exception[/u] und must be [u]catched by boolean query[/u]:

[i]boolean java.io.File#renameTo(File dest)[/i]

> Here we are indeed tempted if not forced to use exception handling because it is the only way we have and that in my opinion is a kludge.

In my example above, we are [b]tempted to forget to test[/b] the boolean return value, and the end-user of our software will come in real trouble, when his system sometime rejects renaming a file. This is a realy kludge also.

dog
Offline
Joined: 2003-08-22

> You are missing that doing a check before then requires
> to do the conversion later again for most cases, so
> this is actually slower.

It may be slower but it is more "correct". The objective is to write readable code not necesarily squeaze out the last bit of performance. If you need performance in a particular isolated chunk of code you can do hacks like the exception thing.. but that should not be the norm.

The problem I see with the Integer.isInteger() function is localization. Particularily with Double.isDouble(). Is 1,0 a number? What about 1 000 000,3 .. is that a Double?

That being said.. I still like the idea. APIs shouldn't require hacks.

monika_krug
Offline
Joined: 2004-10-14

As Double.isDouble(String) is to return true exactly when Double.parseDouble(String) is successful - no, 1,0 is not a double.

Monika.

vpatryshev
Offline
Joined: 2004-06-30

It would be too much to use exceptions to check every string for conformance with a specified format. Like if an iterator were throwing an exception when there are no elements left.

monika_krug
Offline
Joined: 2004-10-14

> i think regular expressions can help you there... you
> can write your code as
>
> String input = "";
> do{
> System.out.print("insert a whole number: ");
> input = bufferedReader.readLine();
> } while (!Pattern.matches("\\d*",input));
> int number = Integer.parseInt(input);

Yes, but this leaves out + and -. Okay, that can be added in the regex. But it still leaves out the cases where the number is too large or too small ("too negative") to be an int.

Monika.

forax
Offline
Joined: 2004-10-07

use a java.util.Scanner instead :

System.out.println(new Scanner("23").hasNextInt());
System.out.println(new Scanner("2333333333").hasNextInt());

Rémi Forax

tjpalmer
Offline
Joined: 2004-07-16

I'd call this one the winner.

hindog_
Offline
Joined: 2005-09-29

I don't know if this is all that necessary of a feature for me. I've always used a utility class to do such things:

[code]
public class NumberUtil
{
public static int parseInt( String value, int defaultValue )
{
try {
defaultValue = Integer.parseInt( value );
} catch ( NumberFormatException ex ) {}
return defaultValue;
}

public static int parseInt( String value )
{
return parseInt( value, 0 );
}

public static boolean isInt( String value )
{
try { Integer.parseInt( value ); return true; }
catch ( NumberFormatException ex ) { }
return false;
}

/* ... double, float, long versions, etc */
}
[/code]
You can then do:
[code]
if ( NumberUtil.isInt( "123" ) ) { ... }
[/code]
With Tiger you can also do static imports, allowing you to do:
[code]
if ( isInt( "123" ) ) { ... }
[/code]

haslo
Offline
Joined: 2005-11-11

I strongly agree with the OP about this issue. I feel that having no function to check whether a given string is a number is a severe limitation of the API.

In a real-world case in a bigger application we're currently developing (several ten thousand SLOC) we actually have a case of a table (two-dimensional array) of Objects we're holding. These are Objects out of flexibility reasons, since this specific table is actually at the very base of the object hierarchy and is holding most of our application's data. Now there's a QuickSort we implemented ourselves for the specific reason that we don't know beforehand if a set column of data consists of doubles or strings - and we want to sort them accordingly.

So, the API does not provide us with any means to do this efficiently. Yeah, we can write an utility class that does this for us, but I feel this is a way too common case to justify it being left out of the API itself. And in addition to that, hiding the exception (which in this case is enormously inefficient, since over half of our values are not numbers and we want to find out if they are) away in an utility class isn't going to get us any performance advantage at all. Seeing how we're speaking about potentially hundreds of rows, this is in no way efficient.

I strongly feel the API should provide such a means of an efficient way for finding out whether a given string is a number or not. Even parsing twice is almost bound to be more efficient than having exceptions thrown in most cases.

Again, we're not speaking about exceptional cases of a rare few objects that won't be numbers. Rather, we're speaking about a few (about 40%) cases where we actually have a number, and we want to handle these correctly. Now having code that says "help, exception, it's not a number" in the majority of cases is simply contra-intuitive.

EDIT: Just look what the most common case for a NumberFormatException is: People asking "how can I check if a number is a double before I have to revert to exceptions?" - with the answer "you can't".
http://www.google.ch/search?q=%22catch%28numberformatexception%29%22+che...

Don't get me wrong, I agree that exceptions are an essential part and that they should be used to handle an exceptional control flow. They should not be used to handle regular control flows though.

Message was edited by: haslo

sjasja
Offline
Joined: 2004-08-15

> In a real-world case in a bigger application we're currently
> Yeah, we can write an utility class that does this for us, but I feel
> this is a way too common case to justify it being left out of the API
> itself.

I find the need for isInteger() very uncommon. Several things have to happen simultaneously:

- I need to parse a large number of integers.
- There is a large percentage of invalid numbers.
- The code is performance critical.
- Everyone in the project is unable or unwilling to write a utility function to do the check.

> Seeing how we're speaking about potentially hundreds of rows, this is
> in no way efficient.

Did you measure the "enormous inefficiency" before worrying about it? My PC can check 130,000 numbers per second, with a mix of 50%/50% numbers and non-numbers. Test program below. So "hundreds of rows" would be a few milliseconds.

I could even write a faster isInteger() function if I needed it. I have written and actually needed hundreds of little utility functions but not that particular one. "I need a two-line helper function so I'll start demanding the language comes with it" is not a particularly effective way for a programmer to behave.
[code]
public class Test
{
public static void main(String args[])
{
System.out.println("Ignore the first few timings.");
System.out.println("They may include Hotspot compilation time.");
System.out.println("I hope you are running me with \"java -server\"!");
for (int n = 0; n < 5; n++)
doit();
}

static void doit()
{
int loops = 100000;
long start = System.currentTimeMillis();
for (int n = 0; n < loops; n++) {
try { Integer.parseInt("123"); } catch (NumberFormatException e) { }
try { Integer.parseInt("hello"); } catch (NumberFormatException e) { }
}
long end = System.currentTimeMillis();

long checks_per_second = loops * 1000 / (end - start) / 2;
System.out.println("time " + (end - start) + " ms, " +
checks_per_second + " checks/s");
}
}
[/code]

Message was edited by: sjasja (typo fix)

jarouch
Offline
Joined: 2004-03-04

> I need to parse a large number of integers.

Who would need it, parse numbers?

> There is a large percentage of invalid numbers.

It need not be so big, few percent is enough.

> The code is performance critical.

Or you just dont want to throw your CPU time out of the window..

> Everyone in the project is unable or unwilling to write a utility function to do the check.

Because Core API does not contain such elementary method as this.

Ad your 'benchmark':

1) you don't use the result of the parsing anywhere
2) you use the best case of value causing parse error
3) you 'forgot' to show times without errors.

I tried to run it at my computer, it gave about 60k lines per sec. When I turned it to double parsing of number (eq. to parse of bad value without need of throwing exception) it did 1.2M per sec. Just 20 times more, I realy do understand that it is tooo little to care about..

sjasja
Offline
Joined: 2004-08-15

>> I need to parse a large number of integers.
>
> Who would need it, parse numbers?

Please do note the words "large number of".

>> There is a large percentage of invalid numbers.
>
> It need not be so big, few percent is enough.

Can you share some of your measurements of a real application that has real performance problems due to a few percent of entered numbers being invalid? What kind of real world performance problems do you keep having?

>> Everyone in the project is unable or unwilling to write a utility function to do the check.
>
> Because Core API does not contain such elementary method as this.

So write one!

> Ad your 'benchmark':
>
> 1) you don't use the result of the parsing anywhere

So what? Has no effect on performance. Try it! I did.

> 2) you use the best case of value causing parse error

What do you mean? Do you mean overflow causing the exception? Or the erroneous string being e.g. "12345hello"? Has no effect on performance. Try it! I did.

> 3) you 'forgot' to show times without errors.

No I did not forget that. I did not show times without errors on purpose. That was the point of the exercise. The previous poster was worried about "enormous inefficiency" when parsing "potentially hundreds" of integers with "over half" of the values not being numbers. I was measuring the case that the previous poster was worried about. If he had said he was worried about parsing 100% genuine integers I would have measured that!

> I tried to run it at my computer, it gave about 60k lines per sec.

Just to check: did you remember to use the "-server" flag?

Do you constantly write programs that genuinely have performance problems due to parsing tens of thousands of bad integers per second?

If you do, why don't you write a method that checks for integer-ness? Obviously you are willing and able to do so?

"I need a two-line helper function so I'll start demanding the language comes with it" is not a particularly effective way for a programmer to behave.

klopperq
Offline
Joined: 2005-09-23

I played around with the code posted above and re-wrote the the function to test for integers rather than use try - catch.

I wrote two checkInt methods, just comment one of them out at a time and run the program. I was amazed at how much faster it is without try - catch.

This was done quickly so the method is not tested exhaustively, but I think it is possible to write a short AND efficient utility method to check for number type values.

[code]
public class Test{
public static void main(String args[]) {
System.out.println("Ignore the first few timings.");
System.out.println("They may include Hotspot compilation time.");
System.out.println("I hope you are running me with \"java -server\"!");
for (int n = 0; n < 10; n++) doit();
}

static void doit() {
int loops = 100000;
long start = System.currentTimeMillis();
for (int n = 0; n < loops; n++) {
checkInt("123");
checkInt("123aa");
}
long end = System.currentTimeMillis();
System.out.println(start);
System.out.println(end);
long checks_per_second = loops * 1000 / (end - start) / 2;
System.out.println("time " + (end - start) + " ms, " +
checks_per_second + " checks/s");
}

static boolean checkInt(String num){
char[] chars = num.toCharArray();
int size = chars.length;
for (int x = 0; x < size; x++){
if ( (chars[x] > 57 || chars[x] < 48) || (x != 1 && chars[x] == '-') ) return false;
}
double d = Double.parseDouble(num);
if(d > Integer.MAX_VALUE || d < Integer.MIN_VALUE) return false;
return true;
}

/*
static boolean checkInt(String num){
try{Integer.parseInt(num);} catch(Exception e){return false;}
return true;
}
*/
}
[/code]

sjasja
Offline
Joined: 2004-08-15

Yeah, that's exactly the kind of little helper functions programmers need to be prepared to write when needed.

If you have a large number of integers with a large percentage of bad ones you could use that method. If all or most of the "badness" is due to non-digits you could remove the parseDouble() call, making it even faster. If only a small percentage of your inputs are bad then not using a checkInt() function at all will be still faster.

Incidentally, my test program has a bug. Where it calculates "checks_per_second" it divides by two; should multiply by two instead. Revised statistics for the person worried about hundreds of calls causing problems: on my PC try/catch handles over half a million parses per second, so a few hundred should take less than a millisecond. If that fraction of a millisecond is a show stopper for you, try klopperg's checkInt().

Measure before optimizing to direct your optimization efforts to where they matter.

klopperq
Offline
Joined: 2005-09-23

On Zarar Siddiqi's Blog - he had a short explanation of why Exception handling is expensive ...

"[i]Keep in mind that constructing stack traces is a fairly expensive operation. When an Exception is created, the JVM needs to literally pause the processing and so it can get a good glimpse of the entire runtime stack - this includes classes, methods, line numbers etc - starting from Thread.run() all the way till the creation of Throwable. From the runtime's point of view, this is acceptable since it's not designed for great Exception handling but to run as fast as possible.[/i]"

klopperq
Offline
Joined: 2005-09-23

Once again just use your reusable utils class

while (MyNumberUtils.isInteger(number){...}

luke_f
Offline
Joined: 2005-07-27

What about something like:

Number.isNumeric(object, size)

where size is Integer.SIZE, Double.SIZE, etc ...

Not the best performance i gather. But it looks ok :)

jwenting
Offline
Joined: 2003-12-02

> What about something like:
>
> Number.isNumeric(object, size)
>
> where size is Integer.SIZE, Double.SIZE, etc ...
>
> Not the best performance i gather. But it looks ok :)

What about simply using the tools you have instead of screaming for MORE MORE MORE to be added to the language?