The Source for Java Technology Collaboration

Home » java.net Forums » JDK » Java SE

Thread: static boolan Integer.isInteger(String)

Welcome, Guest Help
Login Login
Guest Settings Guest Settings
Reply to this Thread Reply to this Thread Search Forum Search Forum Back to Thread List Back to Thread List

Permlink Replies: 78 - Last Post: Nov 16, 2005 10:35 AM by: klopperq
monika_krug

Posts: 144
static boolan Integer.isInteger(String)
Posted: Nov 8, 2004 6:01 AM
  Click to reply to this thread Reply

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 = "";
do
{
  System.out.print("insert a whole number: ");
  input = bufferedReader.readLine();
} while (!Integer.isInteger(input));
int number = Integer.parseInt(input);
instead of like this:
String input = "";
int number = 0;
boolean error = false;
do
{
  System.out.print("insert a whole number: ");
  input = bufferedReader.readLine();
  error = false;
  try
  {
    number = Integer.parseInt();
  }
  catch(NumberFormatException ex)
  {
    error = true;
  }
} 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.

dondi_imperial

Posts: 19
Re: static boolan Integer.isInteger(String)
Posted: Nov 22, 2004 8:22 PM   in response to: monika_krug
  Click to reply to this thread Reply

+1 I don't know why this was not included in java 1.0 :D

zander

Posts: 594
Re: static boolan Integer.isInteger(String)
Posted: Nov 23, 2004 10:15 AM   in response to: monika_krug
  Click to reply to this thread Reply

Truth is; its soo darn easy to make this yourself (your example program can be done in almost halve the size) that an extra method seems silly.
Next think is your going to ask for a Number Number.add(Number, Number).
Hmm. Ok, thats not trivial, but anyway :)

Point is; the implementation is 2 lines, so if you need it then I suggest you put it in a library of your own.
Or, naturally, you learn to program using exceptions since that is the correct way of doing this anyway.

The exceptions way:
int number;
while(true) {
  try {
    number = Integer.parseInt(bufferedReader.readLine());
    break;
  } catch(NumberFormatException e) { }
}


yishai

Posts: 61
Re: static boolan Integer.isInteger(String)
Posted: Nov 23, 2004 2:05 PM   in response to: zander
  Click to reply to this thread Reply

Sure it is easy to do yourself, but you have to rely on the try catch, which is not supposed to be used for flow control. There is no way, short of rewriting the whole JDK function to parse strings, to do this without exception catching (and throwing in the JDK). This is a performance nighmare under certain circumstances. (e.g., validate that all of the values in the second column of a 1,000,000 row CSV file are not numbers).

The frustrating thing is that it would be trivial to do in the underlying JDK code, but when you are stuck with the API, well you are stuck.

zander

Posts: 594
Re: static boolan Integer.isInteger(String)
Posted: Nov 24, 2004 12:52 AM   in response to: yishai
  Click to reply to this thread Reply

> Sure it is easy to do yourself, but you have to rely
> on the try catch, which is not supposed to be used
> for flow control.

Whoa! Exceptions really are all about flow control; how else can you look at it? If you don't see them as flow control, you are not using them optimally.

> This is a performance nighmare under certain
> circumstances. (e.g., validate that all of the values
> in the second column of a 1,000,000 row CSV file are
> not numbers).

Use Character.isDigit(char c)

yishai

Posts: 61
Re: static boolan Integer.isInteger(String)
Posted: Nov 24, 2004 8:35 PM   in response to: zander
  Click to reply to this thread Reply

> Whoa! Exceptions really are all about flow
> control; how else can you look at it? If you don't
> see them as flow control, you are not using them
> optimally.

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."

http://www.ryanlowe.ca/blog/archives/000453_throws_object.php

Using it for simply boolean flow control is a bad practice, performance-wise, not to mention error prone.

> Use Character.isDigit(char c)

This doesn't answer the formal question of is it an Integer, in the sense of will Integer.parseInt(String) throw an exception when you call it on a given value. Integer.parseInt(String) handles the minus sign, and that the number isn't too long, or too large.

zander

Posts: 594
Re: static boolan Integer.isInteger(String)
Posted: Nov 28, 2004 9:25 AM   in response to: yishai
  Click to reply to this thread Reply

> > Use Character.isDigit(char c)
>
> This doesn't answer the formal question of, is it an
> Integer

Thats not what you asked; you asked:

> validate that all of the values
> in the second column of a 1,000,000 row CSV file are
> not numbers.

Where my answer was the right one.

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.

yishai

Posts: 61
Re: static boolan Integer.isInteger(String)
Posted: Nov 28, 2004 9:42 PM   in response to: zander
  Click to reply to this thread Reply

> > > Use Character.isDigit(char c)
> >
> > This doesn't answer the formal question of, is it
> an
> > Integer
>
> Thats not what you asked; you asked:
>
> > validate that all of the values
> > in the second column of a 1,000,000 row CSV file
> are
> > not numbers.
>
> Where my answer was the right one.

That is true. But what about a negative sign in front of the number? My point is, you can rewrite the understanding of a number for each case. But you shouldn't have to. That should be part of the core API. Rewrite it only if your's is different in some special circumstance.


> 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.

I think the basic validation of user input is enough of a use-case. Using such an API makes code clearer, cleaner and faster than an attempt to parse just to see if it would work, and I'd be curious to hear what the case against it is.

zander

Posts: 594
Re: static boolan Integer.isInteger(String)
Posted: Nov 29, 2004 1:53 AM   in response to: yishai
  Click to reply to this thread Reply

> I think the basic validation of user input is enough
> of a use-case.

How do you propose that to validate the input that comes from a file?

> Using such an API makes code clearer,
> cleaner and faster than an attempt to parse just to
> see if it would work

The funny thing is; you have to parse it to see if its OK. So you end up parsing twice; one time for check, and one time to convert.
It can be mathmatically proven that you can not make parsing faster if you want to do it correctly, so you end up doing the exact same work twice.

I'm repeating myself and you fail to address the issue of doing things twice (accept saying its acceptable for you).

yishai

Posts: 61
Re: static boolan Integer.isInteger(String)
Posted: Nov 30, 2004 1:41 PM   in response to: zander
  Click to reply to this thread Reply

> > Using such an API makes code clearer,
> > cleaner and faster than an attempt to parse just
> to
> > see if it would work
>
> The funny thing is; you have to parse it to see if
> its OK. So you end up parsing twice; one time for
> check, and one time to convert.
> It can be mathmatically proven that you can not make
> parsing faster if you want to do it correctly, so you
> end up doing the exact same work twice.
>
> I'm repeating myself and you fail to address the
> issue of doing things twice (accept saying its
> acceptable for you).

I addressed the performance complaint in another post, but here I would like to add that you don't always need to convert to parse. I did a little check through my own project, and found this real world case:


boolean goodPageNum = true;
if (pageNum != null) {
try {
Integer.parseInt(pageNum);
}
catch (NumberFormatException ex) {
goodPageNum = false;
}
}
else {
goodPageNum = false;
}
if (goodPageNum) {
sb.append("&pagenum=");
sb.append(pageNum);
}


The sb StringBuffer here is being used to generate a URL for a GET to a report server. Basically it adds the parameter (as a string, this is a URL) if the string is an Integer.

Sure, you can think of ways to write that without exception handling, but the natural way is to look to the Integer class, and the Integer class can only answer with an exception.

Instead we could have done:


if (Integer.isInteger(pageNum)) {
sb.append("&com.kashrus.report.pagenum=");
sb.append(pageNum);
}


zander

Posts: 594
Re: static boolan Integer.isInteger(String)
Posted: Dec 1, 2004 1:51 PM   in response to: yishai
  Click to reply to this thread Reply

> I would like to add that you don't
> always need to convert to parse. I did a little check
> through my own project, and found this real world
> case:
[snip example]

This example smells; having leading-zeros end up in your stringbuffer. I suggest parsing and converting back using String.valueOf() so you won't have any problems.

> Instead we could have done:
>
>

> if (Integer.isInteger(pageNum)) {
> sb.append("&com.kashrus.report.pagenum=");
> sb.append(pageNum);
> }
>


Or:

try {
sb.append("&pagenum="+ String.valueOf(Integer.parseInt(pageNum)));
} catch(NumberFormatException e) {
//log problem here
}

Which is so much shorter then your 16-line version that I repeat that this, hmm, argument is based on a lack of experience in programming with exceptions on your side. I programmed c, perl and Java (and lots of others). I stick with Java since I embraced the advantages of exceptions. Your code example makes me think you did not.

yishai

Posts: 61
Re: static boolan Integer.isInteger(String)
Posted: Dec 2, 2004 10:20 AM   in response to: zander
  Click to reply to this thread Reply

> > I would like to add that you don't
> > always need to convert to parse. I did a little
> check
> > through my own project, and found this real world
> > case:
> [snip example]
>
> This example smells; having leading-zeros end up in
> your stringbuffer. I suggest parsing and converting
> back using String.valueOf() so you won't have any
> problems.

That depends on your assumptions of where the number came from. It wasn't typed in by a user, so leading zeros aren't possible, and anyway, they don't matter (the URL would work anyway). The example isn't quoted enough to understand the bounds checking, and frankly, that isn't relevant.

> > Instead we could have done:
> >
> >

> > if (Integer.isInteger(pageNum)) {
> >
> sb.append("&com.kashrus.report.pagenum=");
> > sb.append(pageNum);
> > }
> >

>
> Or:
>

> try {
> sb.append("&pagenum="+
> num="+ String.valueOf(Integer.parseInt(pageNum)));
> } catch(NumberFormatException e) {
> //log problem here
> }
>

> Which is so much shorter then your 16-line version
> that I repeat that this, hmm, argument is based on a
> lack of experience in programming with exceptions on
> your side. I programmed c, perl and Java (and lots
> of others). I stick with Java since I embraced the
> advantages of exceptions. Your code example makes me
> think you did not.

Shorter, yes. Readable, no. You have to look at that code carefully to know what your intent is. Very carefully. Also, your code is tremendously inefficient, which in this case isn't a problem, but in a loop it would be. You create an extra string, which is non-trivial to create, catch an exception for flow control, and it made you think about the problem differently. Your comment says it all. You want to log a problem. There is no problem. The page number not being a real number is an expected case, nothing worth noting, any more than noting if it was a 2 or a 3.

Also, this was someone else's code. Which is precisely my real-world point. You will see code like this more frequently in the real world because of the lack of an isInteger method.

So I would say that on both performance and readability, the isInteger case wins.

alexlamsl

Posts: 343
Re: static boolan Integer.isInteger(String)
Posted: May 22, 2005 7:07 PM   in response to: yishai
  Click to reply to this thread Reply

I do think that the try-catch block in this case is clear and readable.

Although from a narrow point of view isInteger() looks clearer than the try-catch approach, on the Language wide level that would mean introducing tons more of these "readable" methods, which would increase the complexity of the core API by such a factor that it would be difficult both to maintain or to comprehend it for basic operations.

ulfzibis

Posts: 72
Re: static boolan Integer.isInteger(String)
Posted: May 23, 2005 2:39 AM   in response to: alexlamsl
  Click to reply to this thread Reply

This sounds realistic.

Although I like the approach by caching the parsing-result of the isInteger method for later usage by valueOf or parseInt. As you see, we have just two methods for parsing a string to an integer. So why not have three, all caching the result.

Perhaps this is a good example for multi return values, to avoid the exception, see: http://forums.java.net/jive/thread.jspa?threadID=670

yishai

Posts: 61
Re: static boolan Integer.isInteger(String)
Posted: Nov 28, 2004 9:57 PM   in response to: zander
  Click to reply to this thread Reply

> 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

Posts: 594
Re: static boolan Integer.isInteger(String)
Posted: Dec 1, 2004 1:59 PM   in response to: yishai
  Click to reply to this thread Reply

> 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).

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;
}



> 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

Posts: 61
Re: static boolan Integer.isInteger(String)
Posted: Dec 2, 2004 9:25 AM   in response to: zander
  Click to reply to this thread Reply

> > 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:

//Horrible abuse of exceptions. Don't ever do this!
try {
int i=0;
while (true)
a[i++].f();
} catch (ArrayIndexOutOfBoundsException e){
}


This is precisely the coding style you advocate for Integer. And it is a bad practice. To quote from the next page (170) "A well-designed API must not force its client to use exceptions for ordinary control flow. 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

Posts: 594
Re: static boolan Integer.isInteger(String)
Posted: Dec 3, 2004 6:11 AM   in response to: yishai
  Click to reply to this thread Reply

> > > 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 any 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) "A well-designed API must not
> force its client to use exceptions for ordinary
> control flow.


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

Posts: 61
Re: static boolan Integer.isInteger(String)
Posted: Dec 3, 2004 7:19 AM   in response to: zander
  Click to reply to this thread Reply

> > 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?

alexlamsl

Posts: 343
Re: static boolan Integer.isInteger(String)
Posted: May 22, 2005 7:14 PM   in response to: yishai
  Click to reply to this thread Reply

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 on the whole would decrease with the introduction of such "friendly" methods, hence the use of the simpler try-catch block is the better choice here.

zander

Posts: 594
Re: static boolan Integer.isInteger(String)
Posted: Nov 28, 2004 9:38 AM   in response to: yishai
  Click to reply to this thread Reply

> > Exceptions really are all about 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

Posts: 61
Re: static boolan Integer.isInteger(String)
Posted: Nov 28, 2004 9:49 PM   in response to: zander
  Click to reply to this thread Reply

> 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

Posts: 594
Re: static boolan Integer.isInteger(String)
Posted: Nov 29, 2004 2:05 AM   in response to: yishai
  Click to reply to this thread Reply

> 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

Posts: 144
Re: static boolan Integer.isInteger(String)
Posted: Nov 29, 2004 4:52 AM   in response to: zander
  Click to reply to this thread Reply

> 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]

jwenting

Posts: 478
Re: static boolan Integer.isInteger(String)
Posted: Nov 30, 2004 11:12 PM   in response to: monika_krug
  Click to reply to this thread Reply

> > 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

Posts: 61
Re: static boolan Integer.isInteger(String)
Posted: Dec 1, 2004 8:44 AM   in response to: jwenting
  Click to reply to this thread Reply

> > > 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?".

lucnelis

Posts: 1
Re: static boolan Integer.isInteger(String)
Posted: Nov 29, 2004 1:10 AM   in response to: zander
  Click to reply to this thread Reply

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).

dondi_imperial

Posts: 19
Re: static boolan Integer.isInteger(String)
Posted: Nov 30, 2004 1:08 AM   in response to: zander
  Click to reply to this thread Reply

What about this?
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);
  }
}

Exceptional condition? I don't think so.

Dondi

ulfzibis

Posts: 72
Re: static boolan Integer.isInteger(String)
Posted: Feb 21, 2005 9:03 AM   in response to: yishai
  Click to reply to this thread Reply

> 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 exceptional situations are not handled by Exception und must be catched by boolean query:

boolean java.io.File#renameTo(File dest)

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

vpatryshev

Posts: 37
Re: static boolan Integer.isInteger(String)
Posted: Feb 21, 2005 8:05 PM   in response to: zander
  Click to reply to this thread Reply

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.

i_salloum

Posts: 1
Re: static boolan Integer.isInteger(String)
Posted: Nov 23, 2004 11:12 PM   in response to: monika_krug
  Click to reply to this thread Reply

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

dondi_imperial

Posts: 19
Re: static boolan Integer.isInteger(String)
Posted: Nov 24, 2004 12:07 AM   in response to: i_salloum
  Click to reply to this thread Reply

I think the original point here is that doing it like this:
if(Integer.isInteger(someObject){
// do something 
}

Is the cleanest, most readable and correct way of doing it. Add to that the fact that the isInteger method is where it is supposed to be and that everyone will write the same code if this were available this would add to everyone's productivity in the long run.

Dondi

zander

Posts: 594
Re: static boolan Integer.isInteger(String)
Posted: Nov 24, 2004 1:25 AM   in response to: dondi_imperial
  Click to reply to this thread Reply

> I think the original point here is that doing it like
> this:
>
if(Integer.isInteger(someObject){
> // do something 
> }

> Is the cleanest, most readable and correct way
> of doing it.

You are missing that doing a check before then requires to do the conversion later again for most cases, so this is actually slower.
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.

> Add to that the fact that the isInteger
> method is where it is supposed to be and that
> everyone will write the same code if this were
> available this would add to everyone's productivity
> in the long run.

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

monika_krug

Posts: 144
Re: static boolan Integer.isInteger(String)
Posted: Nov 24, 2004 6:59 AM   in response to: zander
  Click to reply to this thread Reply

As I said in the first posting:
"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."

It should not be added to Number, because Number.isNumber(String) would return true for e.g. a float, which is no use to us if we want an int.

Monika.

dog

Posts: 49
Re: static boolan Integer.isInteger(String)
Posted: Nov 26, 2004 11:27 AM   in response to: zander
  Click to reply to this thread Reply

> 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

Posts: 144
Re: static boolan Integer.isInteger(String)
Posted: Nov 26, 2004 12:55 PM   in response to: dog
  Click to reply to this thread Reply

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

Monika.

dondi_imperial

Posts: 19
Re: static boolan Integer.isInteger(String)
Posted: Nov 26, 2004 11:14 PM   in response to: zander
  Click to reply to this thread Reply

> 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:
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". While the proposed code:
int num;
if(Integer.isInteger(someString)) num = Integer.parseInt(someString);
else num = 0;

or more concise:
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.

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

Posts: 594
Re: static boolan Integer.isInteger(String)
Posted: Nov 28, 2004 9:16 AM   in response to: dondi_imperial
  Click to reply to this thread Reply

> 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 using 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

Posts: 19
Re: static boolan Integer.isInteger(String)
Posted: Nov 29, 2004 6:41 PM   in response to: zander
  Click to reply to this thread Reply

> 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 using
> 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

Posts: 72
Re: static boolan Integer.isInteger(String)
Posted: Feb 22, 2005 10:27 AM   in response to: dondi_imperial
  Click to reply to this thread Reply

> 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 exceptional situations are not handled by Exception und must be catched by boolean query:

boolean java.io.File#renameTo(File dest)

> 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 tempted to forget to test 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.

monika_krug

Posts: 144
Re: static boolan Integer.isInteger(String)
Posted: Nov 24, 2004 7:01 AM   in response to: i_salloum
  Click to reply to this thread Reply

> 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

Posts: 115
Re: static boolan Integer.isInteger(String)
Posted: Nov 25, 2004 10:52 AM   in response to: monika_krug
  Click to reply to this thread Reply

use a java.util.Scanner instead :

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

Rémi Forax

tjpalmer

Posts: 20
Re: static boolan Integer.isInteger(String)
Posted: Nov 30, 2004 8:48 AM   in response to: forax
  Click to reply to this thread Reply

I'd call this one the winner.

dog

Posts: 49
Re: static boolan Integer.isInteger(String)
Posted: Nov 26, 2004 11:34 AM   in response to: monika_krug
  Click to reply to this thread Reply

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

Posts: 478
Re: static boolan Integer.isInteger(String)
Posted: Dec 3, 2004 5:37 AM   in response to: dog
  Click to reply to this thread Reply

> 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?

s690716

Posts: 20
Re: static boolan Integer.isInteger(String)
Posted: Apr 6, 2005 5:56 PM   in response to: monika_krug
  Click to reply to this thread Reply

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...

kirillcool

Posts: 796
Re: static boolan Integer.isInteger(String)
Posted: Nov 29, 2004 1:31 AM   in response to: monika_krug
  Click to reply to this thread Reply

Here is how the code for parseInt looks in Tiger, judge for yourself how easy it would be to reuse it for the isInteger function:

public static int parseInt(String s, int radix)
throws NumberFormatException
{
if (s == null) {
throw new NumberFormatException("null");
}

if (radix < Character.MIN_RADIX) {
throw new NumberFormatException("radix " + radix +
" less than Character.MIN_RADIX");
}

if (radix > Character.MAX_RADIX) {
throw new NumberFormatException("radix " + radix +
" greater than Character.MAX_RADIX");
}

int result = 0;
boolean negative = false;
int i = 0, max = s.length();
int limit;
int multmin;
int digit;

if (max > 0) {
if (s.charAt(0) == '-') {
negative = true;
limit = Integer.MIN_VALUE;
i++;
} else {
limit = -Integer.MAX_VALUE;
}
multmin = limit / radix;
if (i < max) {
digit = Character.digit(s.charAt(i++),radix);
if (digit < 0) {
throw NumberFormatException.forInputString(s);
} else {
result = -digit;
}
}
while (i < max) {
// 1) {
return result;
} else { /* Only got "-" */
throw NumberFormatException.forInputString(s);
}
} else {
return -result;
}
}

Kirill
http://jroller.com/page/kirillcool/Weblog?catname=/Java


Message was edited by: kirillcool


yishai

Posts: 61
Re: static boolan Integer.isInteger(String)
Posted: Nov 29, 2004 3:10 PM   in response to: kirillcool
  Click to reply to this thread Reply

> Here is how the code for parseInt looks in
> Tiger, judge for yourself how easy it would be to
> reuse it for the isInteger function:

Here is my rewrite (fast and dirty, please no comments on style):


private static int integer(String s, int radix, StringBuffer problem)
throws NumberFormatException
{
if (s == null || s.length() == 0) {
return problem(s, problem);
}

//I think these are fine. You can know what valid Radix's are ahead of time.
if (radix < Character.MIN_RADIX) {
throw new NumberFormatException("radix " + radix +
" less than Character.MIN_RADIX");
}

if (radix > Character.MAX_RADIX) {
throw new NumberFormatException("radix " + radix +
" greater than Character.MAX_RADIX");
}

int result = 0;
boolean negative = false;
int i = 0, max = s.length();
int limit;
int multmin;
int digit;

if (max > 0) {
if (s.charAt(0) == '-') {
negative = true;
limit = Integer.MIN_VALUE;
i++;
} else {
limit = -Integer.MAX_VALUE;
}
multmin = limit / radix;
if (i < max) {
digit = Character.digit(s.charAt(i++),radix);
if (digit < 0) {
return problem(s, problem);
} else {
result = -digit;
}
}
while (i < max) {
// 1) {
return result;
} else { /* Only got "-" */
return problem(s, problem);
}
} else {
return -result;
}
}

private static int problem(String sourceValue, StringBuffer problem) {
problem.append(sourceValue);
return 0;
}

public static int parseInt(String value, int radix) {
StringBuffer problem = new StringBuffer();
int result = integer(value, radix, problem);
if (problem.length() > 0) {
throw NumberFormatException.forInputString(problem.toString());
} else {
return result;
}
}

public static boolean isInteger(String value, int radix) {
StringBuffer problem = new StringBuffer();
integer(value, radix, problem);
return problem.length() == 0;
}


Of course we could imagine making more efficient code that doesn't rely on a StringBuffer creation every time, but fundamentally, it isn't a hard problem to refactor. I was also a little quick'n'dirty on the handling of the 0 length String boundary condition, but that is easily solvable if someone were spending the time on the problem.

frank1russo

Posts: 1
Re: static boolan Integer.isInteger(String)
Posted: Nov 29, 2004 4:49 AM   in response to: monika_krug
  Click to reply to this thread Reply

This is simple to do with regular expressions:

/** regex pattern for an integer */
private static final Pattern intPattern = Pattern.compile("\\d+");

/** Returns true iff the provided string contains only digits */
public static final boolean isInteger(String str) {
return intPattern.matcher(str).matches();
}

kirillcool

Posts: 796
Re: static boolan Integer.isInteger(String)
Posted: Nov 29, 2004 6:12 AM   in response to: frank1russo
  Click to reply to this thread Reply

So, you suppose that a string consisting of a thousand 9's is a valid integer in Java?

monika_krug

Posts: 144
Re: static boolan Integer.isInteger(String)
Posted: Nov 30, 2004 2:00 AM   in response to: monika_krug
  Click to reply to this thread Reply

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?

One possibility is caching the parsed String and number (when isInteger returns true). Then, when parseInt() is called on the same String as isInteger() was called on before, it could be returned immediately.
But this would result in the Integer class holding a reference to the String and to hold the int value, both in static variables. Could this be a problem? A String plus an int is not much memory. Is the comparison too much additional overhead? Probably not, the parsing takes much longer than that.

Another possibility is implementing the isInteger() method in a way that is much shorter than parseInt(). But how could this be done? How long does string.match(regex) need? Is it as long as parseInt()? If it is a lot shorter, isInteger could be implemented somewhat like this:
public boolean isInteger(String s)
{
  if (s==null) return false;
  int n = s.length(); /* to avoid calling s.length() repeatedly */
  if (n == 0 || n > 11 /* 11 is  "-2147483648".length() */) return false;
  
  boolean positiveNumber = false, negativeNumber = false;
 
  /* to avoid calling matches() twice: */
  if (s.substring(1).matches("\\d+"))
  {
    /* to avoid calling charAt(0) thrice */
    char first = s.charAt(0);
    if (first == '-')
    {
      negativeNumber = true;
    }
    else if ( first == '+' || (Character.isDigit(first) && n <= 10) )
    {
      positiveNumber = true;
    }
  
  if(positiveNumber)
  {
    if (n < 10) return true;
    /* == only do actual parsing in the other cases == */
  }
 
  if (negativeNumber)
  {
    if(n < 11) return true;
    /* == only do actual parsing in the other cases == */
  }
  return false;
}


As I said, this assumes that string.matches(regex) would be a lot faster. I am not sure it is.

It would still add overhead for numbers close to the Min and Max.

Monika.

kirillcool

Posts: 796
Re: static boolan Integer.isInteger(String)
Posted: Nov 30, 2004 3:50 AM   in response to: monika_krug
  Click to reply to this thread Reply

Monika, soooo many problems in the functions that you've wrote that i don't even know where to start:

1. It should work for all radixes, so the regex is not good
2. You can't check the length, otherwise 999999999 is OK
3. If you check the length, you should take the radix into account
4. How can it match \\d++ and have a leading minus?

In addition, what static variable should hold the reference? What about multi-thread safe or even two consecutive calls to isInteger?

Kirill
http://jroller.com/page/kirillcool/Weblog?catname=/Java

monika_krug

Posts: 144
Re: static boolan Integer.isInteger(String)
Posted: Nov 30, 2004 7:59 AM   in response to: kirillcool
  Click to reply to this thread Reply

> 1. It should work for all radixes, so the regex is
> not good

Okay, this only works for base 10, but this is the most common use. It's the isInteger(String), not the isInteger(String, int base) method.

> 2. You can't check the length, otherwise 999999999 is
> OK

Look at my code again: Only for length less than the max true is returned and for longer false, in case of the length identical to the max length actual parsing is done. I did not write how this is done, just put a comment that it is done there.

> 3. If you check the length, you should take the radix
> into account

As 1.

> 4. How can it match \\d++ and have a leading
> minus?

Look closely. I match substring(1).

> In addition, what static variable should hold the
> reference?

An additional static variable inside the Integer class.

> What about multi-thread safe

Okay, that is a serious problem. But it can be guaranteed to function correctly if the part where the cached String is compared to the parameter and (if equal) the cached int is returned is in a synchronized block. Then in multi-thread use there will only be the original performance problem, but it will work correctly.

> or even two consecutive calls to isInteger?

The second one will overwrite the cached values from the first one. What else would you expect?

Monika.

yishai

Posts: 61
Re: static boolan Integer.isInteger(String)
Posted: Nov 30, 2004 7:40 AM   in response to: monika_krug
  Click to reply to this thread Reply

> 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

Posts: 144
Re: static boolan Integer.isInteger(String)
Posted: Nov 30, 2004 8:04 AM   in response to: yishai
  Click to reply to this thread Reply

You are absolutely right :-)

Monika.

zander

Posts: 594
Re: static boolan Integer.isInteger(String)
Posted: Dec 1, 2004 2:09 PM   in response to: yishai
  Click to reply to this thread Reply

> 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

Posts: 61
Re: static boolan Integer.isInteger(String)
Posted: Dec 1, 2004 2:25 PM   in response to: zander
  Click to reply to this thread Reply

> > 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.


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


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

Posts: 594
Re: static boolan Integer.isInteger(String)
Posted: Dec 1, 2004 11:46 PM   in response to: yishai
  Click to reply to this thread Reply

> 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

Posts: 61
Re: static boolan Integer.isInteger(String)
Posted: Dec 2, 2004 8:56 AM   in response to: zander
  Click to reply to this thread Reply

> > 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

Posts: 594
Re: static boolan Integer.isInteger(String)
Posted: Dec 3, 2004 6:23 AM   in response to: yishai
  Click to reply to this thread Reply

oops. duplicate..


Message was edited by: zander


zander

Posts: 594
Re: static boolan Integer.isInteger(String)
Posted: Dec 3, 2004 6:27 AM   in response to: yishai
  Click to reply to this thread Reply

> 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:
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;
  }
}


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 very 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

Posts: 1
Re: static boolan Integer.isInteger(String)
Posted: Apr 4, 2005 7:49 PM   in response to: zander
  Click to reply to this thread Reply

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

Posts: 478
Re: static boolan Integer.isInteger(String)
Posted: Apr 5, 2005 1:06 AM   in response to: adeodatus
  Click to reply to this thread Reply

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.

francismok

Posts: 1
Re: static boolan Integer.isInteger(String)
Posted: May 22, 2005 7:44 AM   in response to: adeodatus
  Click to reply to this thread Reply

> 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!

jwenting

Posts: 478
Re: static boolan Integer.isInteger(String)
Posted: Apr 5, 2005 1:05 AM   in response to: monika_krug
  Click to reply to this thread Reply

and I also want isOne(String s), isTwo(String s), isThree(String s) ... all the way to isMaxIntMinusOne(String s).
And of course for negative numbers as well, and every other primitive wrapper type.

s690716

Posts: 20
Re: static boolan Integer.isInteger(String)
Posted: Apr 6, 2005 6:06 PM   in response to: jwenting
  Click to reply to this thread Reply

And don't forget support of octal / hexadecimal represented numbers... so we also need methods like isOctal(String), isHexadecimal(String), isBinary(String) ...

Why a compact API with a small memory footprint, if every method could be integrated in the JRE? And we need a package for primary grade excercise support!

luke_f

Posts: 3
Re: static boolan Integer.isInteger(String)
Posted: Aug 18, 2005 4:42 PM   in response to: monika_krug
  Click to reply to this thread Reply

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

Posts: 478
Re: static boolan Integer.isInteger(String)
Posted: Aug 18, 2005 11:19 PM   in response to: luke_f
  Click to reply to this thread Reply

> 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?

klopperq

Posts: 14
Re: static boolan Integer.isInteger(String)
Posted: Sep 23, 2005 1:50 PM   in response to: jwenting
  Click to reply to this thread Reply

This is where utility classes are so usefull...

public class NumberUtils{
public static boolean isInteger(Number num){
....
}
}

Then we don't have to bloat the APIs and if you are one of those (very few IMHO) people who need to use something like this on a lot of projects its quite reusable...

chandra

Posts: 17
Re: static boolan Integer.isInteger(String)
Posted: Sep 24, 2005 1:29 AM   in response to: klopperq
  Click to reply to this thread Reply

+1

klopperq

Posts: 14
Re: static boolan Integer.isInteger(String)
Posted: Sep 24, 2005 2:45 AM   in response to: monika_krug
  Click to reply to this thread Reply

Once again just use your reusable utils class

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

hindog_

Posts: 1
Re: static boolan Integer.isInteger(String)
Posted: Sep 29, 2005 2:00 PM   in response to: monika_krug
  Click to reply to this thread Reply

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:

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 */
}

You can then do:
if ( NumberUtil.isInt( "123" ) ) { ... }

With Tiger you can also do static imports, allowing you to do:
if ( isInt( "123" ) ) { ... }  


haslo

Posts: 1
Re: static boolan Integer.isInteger(String)
Posted: Nov 10, 2005 11:59 PM   in response to: hindog_
  Click to reply to this thread Reply

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+check+double

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

Posts: 114
Re: static boolan Integer.isInteger(String)
Posted: Nov 11, 2005 3:07 AM   in response to: haslo
  Click to reply to this thread Reply

> 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.
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");
    }
}



Message was edited by: sjasja (typo fix)


jarouch

Posts: 36
Re: static boolan Integer.isInteger(String)
Posted: Nov 11, 2005 3:43 AM   in response to: sjasja
  Click to reply to this thread Reply

> 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

Posts: 114
Re: static boolan Integer.isInteger(String)
Posted: Nov 11, 2005 5:43 AM   in response to: jarouch
  Click to reply to this thread Reply

>> 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

Posts: 14
Re: static boolan Integer.isInteger(String)
Posted: Nov 11, 2005 1:05 PM   in response to: sjasja
  Click to reply to this thread Reply

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.



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;
    }
     */
}


sjasja

Posts: 114
Re: static boolan Integer.isInteger(String)
Posted: Nov 11, 2005 4:10 PM   in response to: klopperq
  Click to reply to this thread Reply

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

Posts: 14
Re: static boolan Integer.isInteger(String)
Posted: Nov 16, 2005 10:35 AM   in response to: sjasja
  Click to reply to this thread Reply

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

"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."




 XML java.net RSS