Z tego, co pan powiedział, tutaj jest to, co bym zrobił:
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
}
}
}
Musisz użyć tymczasowego BigInteger, albo skończysz z Lazarov-tych rozwiązanie, które jest poprawne, ale tak naprawdę nie można zrobić czegoś takiego z powodów wymienionych w komentarzach.
W każdym razie, każdy BigInteger (te, które nie zostaną zwrócone) będzie zbiorem śmieci. Jeśli chodzi o autoboxing, nie sądzę, że jest to coś złego. Możesz także uczynić "BigInteger.valueOf(Long.MAX_VALUE))
" jako stałą. Może kompilator lub JVM zrobi to samodzielnie.
Nie jestem pewien, na ile jest efektywny, a używanie tylko BigIntegera może być dobrym pomysłem (jak zauważył Spotted), ponieważ wątpię, czy naprawdę poprawiłoby to resztę kodu, aby użyć odpowiedniego rozmiaru, i może nawet być podatny na błędy, jeśli spróbujesz użyć tych Liczb ze sobą ... Ale znowu, wszystko zależy od tego, czego potrzebujesz. (I tak, przy użyciu wyjątek jak kontrola przepływu jest naprawdę zły pomysł, ale można dodać połów przymierzyć BigInteger tempNumber = new BigInteger(s);
rzucić swój własny wyjątek, jeśli s
nie jest liczbą w ogóle)
Dla celów rekreacyjnych, zrobiłem rozwiązanie bez użycia BigInteger i tylko z ciągiem parsowania (to jeszcze nie jest to, co polecam zrobić, ale to było zabawne :)
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;
}
Tak, BigInteger zadziała –
BigInteger będzie działać? Ale nie potrzebuję obiektu BigInteger, jeśli wejściowy ciąg znaków może zostać umieszczony w klasie Integer lub Long. –
Możesz uzyskać długość łańcucha, a następnie wyciągnąć wnioski na podstawie tej długości. Z pewnością nie jest to najlepsze podejście, a zamiast tego po prostu użyłbym BigIntegera. –