Из того, что вы сказали, вот что я сделал бы:
import java.math.BigInteger;
import java.util.Arrays;
import java.util.List;
public class TestSO09_39463168_StringToMinimalNumber {
public static void main(String[] args) {
List<String> strNumbers = Arrays.asList("0", //int
"123", //int
"-456", //int
"2147483700", // Long
"-2147483700", // Long
"9223372036854775900", //BigInt
"-9223372036854775900" //BigInt
);
for(String strNumber : strNumbers){
Number number = stringToMinimalNumber(strNumber);
System.out.println("The string '"+strNumber+"' is a "+number.getClass());
}
}
public static Number stringToMinimalNumber(String s){
BigInteger tempNumber = new BigInteger(s);
if(tempNumber.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0 || tempNumber.compareTo(BigInteger.valueOf(Long.MIN_VALUE)) < 0){
return tempNumber;
} else if(tempNumber.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) > 0 || tempNumber.compareTo(BigInteger.valueOf(Integer.MIN_VALUE)) < 0){
return tempNumber.longValue(); //Autobox to Long
} else {
return tempNumber.intValue(); //Autobox to Integer
}
}
}
Вы должны использовать временный BigInteger, иначе вы будете в конечном итоге с Lazarov годов решение, которое является правильным, но вы не можете сделать что-то подобное по причине, упомянутой в комментариях.
В любом случае, каждый BigInteger (тот, который не возвращается) будет собираться мусором. Что касается автобоксинга, я не думаю, что это плохо. Вы также можете сделать «BigInteger.valueOf(Long.MAX_VALUE))
» постоянной. Возможно, компилятор или JVM сделают это самостоятельно.
Я не уверен, насколько он эффективен, и использование только BigInteger может быть хорошей идеей (как Пятнистый сделал), потому что я serioulsy сомневаюсь, что это действительно улучшит остальную часть вашего кода, чтобы использовать правильный размер, и это может быть даже подвержено ошибкам, если вы попытаетесь использовать эти Числа друг с другом ... Но опять же все зависит от того, что вам нужно. (и да, использование Exception в качестве управления потоком - это действительно плохая идея, но вы можете добавить попытку поймать на BigInteger tempNumber = new BigInteger(s);
, чтобы выбросить свое собственное исключение, если s
не является номером вообще)
В целях отдыха я сделал решение без использования BigInteger, и только строки разбора (это еще не то, что я Recommand сделать, но это было весело :)
public static final String INT_MAX_VALUE = "2147483647";
public static final String LONG_MAX_VALUE = "9223372036854775807";
public static Number stringToMinimalNumberWithoutBigInteger(String numberStr){
//Removing the minus sign to test the value
String s = (numberStr.startsWith("-") ? numberStr.substring(1,numberStr.length()) : numberStr);
if(compareStringNumber(s, LONG_MAX_VALUE) > 0){
return new BigInteger(numberStr);
} else if(compareStringNumber(s, INT_MAX_VALUE) > 0){
return new Long(numberStr);
} else {
return new Integer(numberStr);
}
}
//return postive if a > b, negative if a < b, 0 if equals;
private static int compareStringNumber(String a, String b){
if(a.length() != b.length()){
return a.length() - b.length();
}
for(int i = 0; i < a.length(); i++){
if(a.codePointAt(i) != b.codePointAt(i)){ //Or charAt()
return a.codePointAt(i) - b.codePointAt(i);
}
}
return 0;
}
Да, BigInteger будет работать –
BigInteger будет работать? Но мне не нужен объект BigInteger, если входная строка может быть размещена внутри Integer или Long. –
Вы можете получить длину строки и затем сделать выводы на основе этой длины. Это, конечно, не лучший подход, и я бы просто использовал BigInteger. –