Преобразуйте любую числовую строку (int, float, double, long и т. д.) в соответствующее числовое значение (int, float, double, long и т. д.) в java

Есть ли лучшая практика для преобразования любой строки входного числа (int, double и т. д.) в соответствующий объект/примитивный тип объекта Wrapper в java?

Этого можно достичь с помощью методов valueOf() или parseXXX(). но я должен знать базовый формат строки, прежде чем выбирать соответствующий тип.

Что я делаю, так это анализирую числовую строку на длинную, используя NumberUtils из commons-lang.jar следующим образом:

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

но проблема в том, что если numberString имеет значение double, то он не сможет разобрать число и вернет 0.0 как проанализированное значение. Только следующий оператор отлично работает для двойных значений:

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

Есть ли общий способ сделать это? также я не забочусь о цифрах после запятой.

Спасибо за чтение.

Обновить

Это выглядит элегантным решением для меня, предложенным @Thomas:

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

поскольку метод parse() возвращает объект-оболочку Long или Double, его можно проверить и соответственно назначить для общего использования. Единственная загвоздка здесь в том, что parse() может выдать ParseException, поэтому с ним нужно обращаться в соответствии с требованиями.

Я использовал это, чтобы решить свою проблему, но мне любопытно узнать о любых других решениях!


person Diablo    schedule 11.11.2014    source источник
comment
Если вам нужен только длинный, просто сделайте так, как вы делаете, разбирайте все, чтобы удвоить или плавать, потому что он должен принимать любой тип int, float, double и т. д., а затем просто приведите его к длинному. Пока ваше число не превышает максимальное двойное значение, вы должны быть в порядке...   -  person brso05    schedule 11.11.2014
comment
Если вам нужны определенные типы в зависимости от строки, я бы использовал регулярное выражение...   -  person brso05    schedule 11.11.2014
comment
Вы можете использовать DecimalFormat#parse(), который с настройками по умолчанию должен возвращать Double для чисел с плавающей запятой и Long для целых чисел.   -  person Thomas    schedule 11.11.2014
comment
Есть ли лучшая практика для преобразования любой входной числовой строки (int, double и т. д.) в соответствующий объект/примитивный тип объекта-оболочки в java. Я ищу, чтобы принять числовую строку и разобрать его на длинный.. Что он? Это две разные цели.   -  person Duncan Jones    schedule 11.11.2014
comment
Что вы на самом деле пытаетесь сделать здесь? Spring имеет продуманную систему преобразования типов, которая во многих случаях может применяться автоматически.   -  person chrylis -cautiouslyoptimistic-    schedule 11.11.2014
comment
@Дункан! Прошу прощения за неясность. Во втором утверждении я попытался выразить свое требование и то, как я его достиг. Вопрос в первом утверждении касается наилучшей практики. TY за указание, я обновил свой вопрос   -  person Diablo    schedule 11.11.2014
comment
@brso05! регулярное выражение? пожалуйста, уточните, как этого можно достичь?   -  person Diablo    schedule 11.11.2014
comment
@Diablo Боюсь, я все еще в замешательстве. Вам нужно общее решение для всех типов данных или вас просто интересует создание значений Long?   -  person Duncan Jones    schedule 11.11.2014
comment
Вам не нужно регулярное выражение, если вам нужны только длинные значения?   -  person brso05    schedule 11.11.2014
comment
С помощью регулярного выражения вы можете сначала проверить, существует ли файл . в числовой строке, если есть, вы можете выбрать соответствующий тип данных, если нет, то вы знаете, что это целое число...   -  person brso05    schedule 11.11.2014
comment
@Томас! parse() выглядит идеально! Я изучаю это!   -  person Diablo    schedule 11.11.2014
comment
Это выглядит элегантным решением для меня, предложенным @Thomas: NumberFormat numberFormat = NumberFormat.getNumberInstance(); long longValue = numberFormat.parse(targetFieldValue).longValue(); поскольку метод parse() возвращает объект-оболочку Long или Double, его можно проверить и соответственно назначить для общего использования. Единственная загвоздка здесь в том, что parse() может бросить ParseException, поэтому его нужно поймать и обработать в соответствии с требованиями.   -  person Diablo    schedule 11.11.2014
comment
@Diablo Хотя мне все еще неясны ваши точные требования, вы видели NumberUtils.createNumber()? Он предназначен для преобразования строки в соответствующий тип оболочки.   -  person Duncan Jones    schedule 12.11.2014


Ответы (2)


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

Приведение здесь предполагает, что вы довольны усечением десятичного числа, независимо от sign (наличие - в строке будет означать, что isDigits возвращает false). Если нет, выполните соответствующее округление.

Если вы опасаетесь, что строка может содержать алфавиты, используйте вариант createLong, который выдаст NumberFormatException вместо 0 по умолчанию.

person mystarrocks    schedule 11.11.2014
comment
Одна потенциальная проблема заключается в том, что isDigits вернет false для отрицательных чисел, поэтому вы должны вызывать toDouble для отрицательного длинного значения. - person Sbodd; 11.11.2014
comment
это не элегантное решение, чем (long) NumberUtils.toDouble(numberString), не так ли? - person Diablo; 11.11.2014
comment
Может быть, в зависимости от того, что вы определяете как элегантность;) - person mystarrocks; 11.11.2014

Мне нужен был более сложный подход, так как я хотел сериализовать "1.0" как double, а не как int, поэтому я реализовал свое собственное решение и оставил его на будущее:

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

Формат такой же, как и в Java, поэтому целые числа без буквы «L» в конце будут преобразованы в целые числа, в противном случае — в длинные. Десятичные числа будут преобразованы в двойные числа, если они не заканчиваются на «f», в этом случае они будут преобразованы в числа с плавающей запятой. Проходят следующие тесты:

    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);
person Bálint Kriván    schedule 11.02.2016