0

Is there a better practice to convert any input number string (int, double, etc) to it's respective Wrapper object/primitive type in java?

Using valueOf() or parseXXX() methods it can achieved. but I should be knowing the underlying string format before selecting the appropriate type.

What I am doing is parsing number string to long, using the NumberUtils from commons-lang.jar as follows:

long longValue= (long) NumberUtils.toLong(numberString);

but the problem is If the numberString has a double value, then it fails to parse to number and will return 0.0 as parsed value. Only the following statement works fine for double values :

Long longValue = (long) NumberUtils.toDouble(numberString);

Is there a generic way of doing this? also I don't care about the digits after the decimal.

Thanks for reading.

Update

This looks elegant solution to me, suggested by @Thomas :

NumberFormat numberFormat = NumberFormat.getNumberInstance(); long longValue = numberFormat.parse(targetFieldValue).longValue();

as the parse() method returns Long or Double wrapper object, It can be checked and assigned accordingly for generic use. Only catch here is that the parse() could throw ParseException, so need to be handled according to the requirement.

I've used this to solve my problem, but curious to know about any other solutions!!

Diablo
  • 443
  • 7
  • 21
  • 2
    If you only want long then just do how you are doing parse everything to double or float because it should accept any type int, float, double, etc... then just cast to long. As long as your number doesn't exceed the max double value you should be fine... – brso05 Nov 11 '14 at 14:13
  • 1
    If you need specific types depending on the string then I would use regex... – brso05 Nov 11 '14 at 14:14
  • You could use `DecimalFormat#parse()` which with default settings should return `Double` for floating point numbers and `Long` for integers. – Thomas Nov 11 '14 at 14:23
  • 2
    "*Is there a better practice to convert any input number string (int, double, etc) to it's respective Wrapper object/primitive type in java.*" "*What I am looking for is to accept a number string and parse it to long.*". Which is it? Those are two different objectives. – Duncan Jones Nov 11 '14 at 14:23
  • What are you actually trying to get done here? Spring has a thorough type-conversion system that can get applied automatically in many cases. – chrylis -cautiouslyoptimistic- Nov 11 '14 at 14:29
  • @Duncan! I apologize for not being clear. In the second statement I tried expressing my requirement and how I've achieved it. The question in the first statement is about best practice of doing it. TY for pointing it, I've updated my question – Diablo Nov 11 '14 at 15:07
  • @brso05! regex? please elaborate how can achieve it? – Diablo Nov 11 '14 at 15:09
  • 1
    @Diablo I'm afraid I'm still confused. Do you want a general solution for all data types or are you just interested in creating `Long` values? – Duncan Jones Nov 11 '14 at 15:10
  • You don't need regex if you only want long values? – brso05 Nov 11 '14 at 15:13
  • With regex you can first check if there is a . in the number string if there is you can choose appropriate data type if not then you know its an integer... – brso05 Nov 11 '14 at 15:14
  • @Thomas! parse() looks perfect! I'm exploring it! – Diablo Nov 11 '14 at 15:21
  • This looks elegant solution to me, suggested by @Thomas : `NumberFormat numberFormat = NumberFormat.getNumberInstance(); long longValue = numberFormat.parse(targetFieldValue).longValue();` as the `parse()` method returns `Long` or `Double` wrapper object, It can be checked and assigned accordingly for generic use. Only catch here is that the `parse()` could throw `ParseException`, so need to be catched and handled according to the requirement. – Diablo Nov 11 '14 at 15:51
  • @Diablo While I'm still unclear of your exact requirement, have you seen [`NumberUtils.createNumber()`](http://commons.apache.org/proper/commons-lang/javadocs/api-release/org/apache/commons/lang3/math/NumberUtils.html#createNumber%28java.lang.String%29)? It's designed to convert a string to the appropriate wrapper type. – Duncan Jones Nov 12 '14 at 08:31

2 Answers2

0
import static org.apache.commons.lang3.math.NumberUtils.isDigits;
import static org.apache.commons.lang3.math.NumberUtils.toDouble;
import static org.apache.commons.lang3.math.NumberUtils.toLong;    

public static void main(String[] args) {
  String numberString = "-23.56";
  long longNumber = (isDigits(numberString) ? toLong(numberString) : (long) toDouble(numberString));
  System.out.println(longNumber);
}

The cast here assumes that you are happy with truncating the decimal, regardless of the sign (the presence of - in the string would mean isDigits returns false). If not, do the appropriate rounding.

If you fear the string might contain alphabets, use the createLong variant that would throw a NumberFormatException instead of defaulting to 0.

mystarrocks
  • 4,040
  • 2
  • 36
  • 61
0

I've needed a more sophisticated approach, since I wanted "1.0" serialized as a double, not as an int so I implemented my own solution and I leave it for the future:

public Number deserialize(CharSequence text) {
    Preconditions.checkArgument(Objects.requireNonNull(text).length() > 0);

    switch (text.charAt(text.length() - 1)) {
        case 'L':
            return Long.parseLong(text.subSequence(0, text.length() - 1).toString());
        case 'f':
            return Float.parseFloat(text.toString());
        default:
            Number number = Ints.tryParse(text.toString());
            if (number == null) {
                number = Doubles.tryParse(text.toString());
            }
            if (number == null) {
                throw new IllegalArgumentException("Unsupported number: " + text);
            }
            return number;
    }
}

The format follows the way as in Java, so integers without 'L' at the end will be converted to Integers otherwise Longs. Decimal numbers will be converted into Doubles unless they end with 'f' in that case they will be converted to Floats. The following tests are passing:

    EXPECT.that(deserialize("1")).isEqualTo(1);
    EXPECT.that(deserialize("5L")).isEqualTo(5L);
    EXPECT.that(deserialize("2.0")).isEqualTo(2.0);
    EXPECT.that(deserialize("4.0f")).isEqualTo(4.0f);
Bálint Kriván
  • 273
  • 2
  • 6