11

There are some situation that I need to convert string to float or some other numerical data-type but there is a probability of getting some nonconvertible values such as "-" or "/" and I can't verify all the values beforehand to remove them. and I want to avoid using try/catch for this matter , is there any other way of doing a proper conversion in java? something similar to C# TryParse?

Edward Brey
  • 40,302
  • 20
  • 199
  • 253
Vahid Hashemi
  • 5,182
  • 10
  • 58
  • 88
  • why the artificial constraint on no exceptions? AFAIK, you'll have to roll your own! – Nim Dec 02 '11 at 20:18
  • Look at http://stackoverflow.com/a/1102916/1071777 The isNumeric method by CraigTP will basically be the tryParse (you can modify it according to your needs) – user1071777 Dec 02 '11 at 20:20
  • its not me to troll myself its an I/O based data coming from somewhere so I have to make it sane – Vahid Hashemi Dec 02 '11 at 20:20
  • question is: if it's dodgy, surely you want to fail fast and not proceed? – Nim Dec 02 '11 at 20:21
  • @Nim, I wouldn't call it an artificial constraint at all, it's simply exploring to see if similar exception-avoiding functionality exists in Java as it does in .NET's TryParse. – Anthony Pegram Dec 02 '11 at 20:22
  • @austinpowers Why not just use a regex to verify the string is what you want if you don't want to leverage the framework and catch the exception? The exception is explicitly defined to state that the number format is incorrect. Your fighting the framework here. – Aaron McIver Dec 02 '11 at 20:22
  • @AnthonyPegram, hmm, seems a waste of time to me... catch the exception, and handle it - bound to be **much** quicker than any other hacky approach... – Nim Dec 02 '11 at 20:25
  • 4
    @Nim, you would be wrong about the "much quicker" claim, if you keep in mind coming from a C# perspective. `float.TryParse` is *orders of magnitude* faster when dealing with an improper input. Exception handling is slow, and we also do not like relying upon exceptions for control flow. So since Austin is coming from a C# perspective, he's looking for that same fast, non-exceptional validation of the input while simultaneously providing the output. You only learn that it does not exist in Java by seeking guidance! – Anthony Pegram Dec 02 '11 at 20:35
  • @Anthony really? Exception handling is slow? Well in an exceptional case yes, but to avoid, you'd rather hit all operations with the same overhead? – Nim Dec 02 '11 at 21:43
  • 1
    @Nim, why would you think TryParse in .NET comes with a lot of overhead? Have you run profiling comparisons for the happy path and exceptional paths between the various number parsing techniques in order to come away with that conclusion, or are you merely assuming? – Anthony Pegram Dec 02 '11 at 22:03
  • But consider the context, not all parsing in .NET would be done with TryParse. If, for example, the data was coming from a known system that could be trusted, then an invalid format would *truly* be exceptional and we would want to treat it as such. If, however, we were dealing with user input, then an invalid input is a much more regular event, and we would want to treat that accordingly. We would not do that by doing exception handling, we would simply validate and reprompt. – Anthony Pegram Dec 02 '11 at 22:04
  • @AnthonyPegram, I didn't claim any such thing, I have no C# experience at all, but from the little Java and C++ knowledge I have, and the code (which I'd consider as being of exceptional quality, that I have seen), I've not seen a case where exceptions are avoided because they are "expensive". Exceptions are abused, but used correctly, it's likely to be cheaper than running a regular expression to check first(?) Ofcourse context matters, but let me put this to you, if you were validating user input, does the "cost" of an exception matter? – Nim Dec 02 '11 at 22:49
  • 2
    @Nim, that goes back to the second part. If I'm validating user input, I'm not going to let an exception drive my decision making. That's making exceptions part of the control flow, and that's bad programming practice in .NET. Again, if you're in an environment that does not have this approach, you use the tools you have. In .NET, we have TryParse, and it's fast, functional, and entirely appropriate for its typical usage. Your environment may differ, just as Java obviously does. – Anthony Pegram Dec 02 '11 at 23:41
  • I think it can help you [Click here](https://stackoverflow.com/a/16699049/6636122). – BertKing Sep 25 '17 at 06:57

5 Answers5

6

The simplest thing I can think of is java.util.Scanner . However this approach requires a new Scanner instance for each String.

String data = ...;
Scanner n = new Scanner(data);
if(n.hasNextInt()){//check if the next chars are integer
  int i = n.nextInt();   
}else{

}

Next you could write a regex pattern that you use to check the String (complex to fail too big values) and then call Integer.parseInt() after checking the string against it.

Pattern p = Pattern.compile("insert regex to test string here");
String data = ...;
Matcher m = p.matcher(data);
//warning depending on regex used this may 
//only check part of the string
if(m.matches()){
  int i = Integer.parseInt(data);
}

However both of these parse the string twice, once to test the string and a second time to get the value. Depending on how often you get invalid strings catching an exception may be faster.

josefx
  • 15,506
  • 6
  • 38
  • 63
  • and the regex is "((-|\\+)?[0-9]+(\\.[0-9]+)?)+" – Vahid Hashemi Dec 02 '11 at 21:08
  • I'm sorry, but I would argue that the regular expression check approach will be slower than simply catching a parse exception, seems like premature optimization to me. – Nim Dec 02 '11 at 21:41
  • @Nim thats why I wrote last sentence and most likely the reason why java does not have a try parse, its slower when most values are valid. – josefx Dec 03 '11 at 10:11
  • In case anyone in the future wants a good solution for doubles, here's the regex for that: `^[-+]?[0-9]*\.?[0-9]+$` and it wont allow for anything else in the string to be anything but numbers (so don't worry about the warning comment in the code above) – kentcdodds May 16 '12 at 11:50
  • Not sure if apache just uses a try-catch but for anyone looking here who just wants a utility method, there is NumberUtils.toInt(str, defaultValue): http://commons.apache.org/proper/commons-lang/javadocs/api-3.3.2/org/apache/commons/lang3/math/NumberUtils.html#toInt(java.lang.String,%20int) – Skystrider Jan 18 '21 at 17:12
  • I confirmed, Apach is using try catch. – Skystrider Jan 18 '21 at 17:30
5

Unfortunately, there is no such method in Java. There is no out parameter in Java, so writing such a method would need to return a null Float to signal an error, or to pass a FloatHolder object which could be modified by the method:

public class FloatHolder {
    private float value;

    public void setValue(float value) {
        this.value = value;
    }

    public float getValue() {
        return this.value;
    }
}

public static boolean tryParseFloat(String s, FloatHolder holder) {
    try {
        float value = Float.parseFloat(s);
        holder.setValue(value);
    }
    catch (NumberFormatException e) {
        return false;
    }
}
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • my point is : avoid using try/catch for parse such simple values , yet thanks for the approach – Vahid Hashemi Dec 02 '11 at 20:19
  • Except by reimplementing parseFloat yourself, you won't be able to do it. If all your code uses the tryParseFloat method, it doesn't have to deal with exceptions. Only tryParseFloat does. – JB Nizet Dec 02 '11 at 20:23
  • can you not use a `Float`? (my java is a little rusty) - what's with the `FloatHolder`? – Nim Dec 02 '11 at 20:23
  • You can use a Float and return null to signal an error. I suggested it in my answer. The FloatHolder is a way to have a signature similar to C#'s TryParse method. – JB Nizet Dec 02 '11 at 20:26
2

This is an old question, but since all the answers fail to mention this (and I wasn't aware of it myself until seeing it in a merge request written by a colleague), I want to point potential readers to the Guava Floats and Ints classes:

With the help of these classes, you can write code like this:

    Integer i = Ints.tryParse("10");
    Integer j = Ints.tryParse("invalid");
    Float f = Floats.tryParse("10.1");
    Float g = Floats.tryParse("invalid.value");

The result will be null if the value is an invalid int or float, and you can then handle it in any way you like. (Be careful to not just cast it to an int/float, since this will trigger a NullPointerException if the value is an invalid integer/floating point value.)

Note that these methods are marked as "beta", but they are quite useful anyway and we use them in production.

For reference, here are the Javadocs for these classes:

Per Lundberg
  • 3,837
  • 1
  • 36
  • 46
1

Java does not provide some built in tryParse type of methods, on of the solutions you can try is to create your own tryParse Method and put try/catch code in this method and then you can easily use this method across your application very easily and without using try/catch at all the places you use the method.

One of the sample functions can have following code

public static Long parseLong(String value) {

        if(isNullOrEmpty(value)) {
            return null;
        }

        try {
            return Long.valueOf(value);
        }
        catch (NumberFormatException e) {
        }

        return null;
    }
Kamran Ali
  • 5,904
  • 2
  • 26
  • 36
0

Regular expressions helped me solve this issue. Here is how:

  1. Get the string input.
  2. Use the expression that matches one or more digits.
  3. Parse if it is a match.
String s = "1111";
int i = s.matches("^[0-9]+$") ? Integer.parseInt(s) : -1;
if(i != -1)
  System.out.println("Integer");
else
  System.out.println("Not an integer");
Amjad Abujamous
  • 736
  • 9
  • 9