我必须编写一个可以获取Number对象(Java)数组的SUM()方法。所以它可能是几个Short对象,然后是几个Floats,然后是BigDecimal。
如果所有内容都是Byte / Short / Integer / Long,那么返回的值应该是Long。
如果所有内容都是Byte / Short / Integer / Long / Float / Double,那么返回的值应该是Double。
如果与上面的混合中有一个BigDecimal,那么结果应该是一个BigDecimal。如果BigInteger在那里,那么我不知道是什么/如何处理它,因为每个BigInteger可以对它处理的数字的大小有不同的值。
目前我收集了一个长的运行总数(所有字节/短/整数/长),双(所有浮点/双)和bigDecimal。然后在最后添加到已使用的任何一个(我有2个布尔跟踪)并返回。
它有效,但它不干净。有没有更简单的方法?一种添加两个Number对象的方法,它返回相应的Number对象?
答案 0 :(得分:0)
根据您对long / double / BigDecimal返回值的要求,可能没有更好的方法。我会这样离开,或者只返回一个BigDecimal - 支持所有类型和大小。有没有理由你不这样做?
但是,您可以稍微增强设计并创建某种类型的Map或枚举,为每种类型提供返回类型参数并授予它们“强度”,以使BigDecimal覆盖Long等。
答案 1 :(得分:0)
Numbers
,这对你有所帮助。看一下源代码:
https://github.com/pmeisen/gen-misc/blob/master/src/net/meisen/general/genmisc/types/Numbers.java
一般来说,
determineCommonType
方法确定所有Number
个实例的常见类型castToNumber
Number
接口不提供这样的方法,您必须自己编写或使用类似longValue
的内容,请参阅https://docs.oracle.com/javase/7/docs/api/java/lang/Number.html#longValue())。当然,也可以将所有内容映射到BigDecimal
,然后使用适当的Number
实现将其强制转换回公共类型(例如,如果你想要长的话,可以将longValue)。
注意强>:
Number
实现(例如AtomicInteger
),但我认为它可以很容易地增强。Integers
可能需要返回Long
答案 2 :(得分:0)
没有很好的方法可以做到这一点,但你可以把它分解成许多更小,更简单的方法。我的方法是建立一个类型的层次结构。理想情况下,添加只涉及较低级别的类型。一旦你找到适当的级别来进行添加,你可以调用适当的方法。这是我的代码(未经过测试)。
private static final Map<Class<? extends Number>, Integer> RANKS;
static {
Map<Class<? extends Number>, Integer> map = new IdentityHashMap<>();
map.put(Byte.class, 0);
map.put(Short.class, 1);
map.put(Integer.class, 2);
map.put(Long.class, 3);
map.put(BigInteger.class, 4);
map.put(Float.class, 5);
map.put(Double.class, 6);
map.put(BigDecimal.class, 7);
RANKS = Collections.unmodifiableMap(map);
}
private static Number addBytes(Number... numbers) {
byte a = 0;
for (Number number : numbers)
a += number.byteValue();
return a;
}
private static Number addShorts(Number... numbers) {
short a = 0;
for (Number number : numbers)
a += number.shortValue();
return a;
}
private static Number addInts(Number... numbers) {
int a = 0;
for (Number number : numbers)
a += number.intValue();
return a;
}
private static Number addLongs(Number... numbers) {
long a = 0;
for (Number number : numbers)
a += number.longValue();
return a;
}
private static Number addBigIntegers(Number... numbers) {
BigInteger a = BigInteger.ZERO;
for (Number number : numbers)
a = a.add(number instanceof BigInteger ? (BigInteger) number : BigInteger.valueOf(number.longValue()));
return a;
}
private static Number addFloats(Number... numbers) {
float a = 0;
for (Number number : numbers)
a += number.floatValue();
return a;
}
private static Number addDoubles(Number... numbers) {
double a = 0;
for (Number number : numbers)
a += number.doubleValue();
return a;
}
private static Number addBigDecimals(Number... numbers) {
BigDecimal a = BigDecimal.ZERO;
for (Number number : numbers) {
a = a.add(
number instanceof BigDecimal ? (BigDecimal) number
: number instanceof BigInteger ? new BigDecimal((BigInteger) number)
: new BigDecimal(number.doubleValue()));
}
return a;
}
public static Number add(Number... numbers) {
if (numbers.length == 0)
return 0;
int max = -1;
for (Number number : numbers) {
Integer rank = RANKS.get(number.getClass());
if (rank == null)
throw new IllegalArgumentException();
max = Math.max(max, rank);
}
switch (max) {
case 0: return addBytes(numbers);
case 1: return addShorts(numbers);
case 2: return addInts(numbers);
case 3: return addLongs(numbers);
case 4: return addBigIntegers(numbers);
case 5: return addFloats(numbers);
case 6: return addDoubles(numbers);
case 7: return addBigDecimals(numbers);
default: throw new IllegalStateException();
}
}