[英]Java: Generic collection for holding primitives of different types
这可能是一个愚蠢的问题,但是Java中是否有一种类型的集合可以容纳不同类型的原语? 我当前正在创建一种格式化两种类型的对象的方法,并且尝试将参数存储在数组中,以避免使用带有十多个参数的方法,而是使用两个数组来保存值并将它们传递给它们。
类型将是字符串,整数和布尔值的组合。
Java中的基元可以装箱成对象。 通过将原始int
值存储为Integer
对象,并将原始boolean
值存储为Boolean
对象, Object
类型可以保存String
, int
和boolean
类型的值。 这通常可以隐式完成,而无需程序员显式包装或拆开它们,这称为自动装箱。
因此,任何保存Object
类型为Object[]
值的集合或数组,例如Object[]
, List<Object>
等,都可以保存您的值。
例如:
Object[] array = new Object[] { 1, 2, true, "hi" };
List<Object> list = new ArrayList<Object>();
list.add(5);
list.add(false);
list.add("test");
对于方法的可变参数,只需使用Object...
:
void myMethod(Object... params) {
// ...
}
当处理Object
值的数组或集合时,可以使用instanceof
和强制类型转换来找到类型并正确处理它们。
自动装箱以键入Object
,将原语直接装箱到Object
值中。 在下面的代码中:
short shortValue = 0;
int myPrimitive = shortValue;
Object myObject = shortValue;
myPrimitive
的类型为int
,但myObject
的类型为Short
。 您要一个Object
,就得到了一个Object
! 要注意关于Object
类型的Object
假设,因为从原则Object
,除了它是一个Object
之外,您不能假设其他任何东西。
幸运的是,您不必总是检查每种原始数字类型的Object
。 在大多数情况下,将其转换为Number
,然后使用例如.intValue()
来获取int类型的值就足够了。 也就是说,这样的代码:
double x = 2.3;
Object o = x;
int i = ((Number) o).intValue();
等效于此:
double x = 2.3;
int i = (int) x;
在Java中,唯一可以保存整数的“集合”是数组,并且它只能保存单一类型的基元。
如果需要收集多种类型的基元,则可以创建一个具有多个基元成员的类,然后使用要存储该类的多个实例的任何Collection。
假设您确实需要一个这样的集合,而您希望避免为值装箱的费用,那么您可以通过背对已经实现的原始集合( 例如Trove)很容易地自己实现这样的集合。 由于您没有指定所需的集合类型,因此让我们看一下将原始整数映射到您命名的值的示例映射:
class PrimitiveMap {
final TIntBooleanMap booleans;
final TIntIntMap ints;
final TIntObjectMap<String> strings;
// Constructor omitted
void putBoolean(int index, boolean value) {
removeIndex(index);
booleans.put(index, value);
}
boolean getBoolean(int index) {
booleans.get(index);
}
// similarly for the other collection types
private removeIndex(int index) {
booleans.remove(index);
ints.remove(index);
strings.remove(index);
}
}
一个明显的缺点是您需要记住所插入元素的类型。 或者,您可以在访问集合时使用盒装值,但在存储值之前先解析该盒:
public void put(Object value) {
if(value instanceof Boolean) {
putBoolean((Boolean) value);
} else if(value instanceof Integer) {
putInteger((Integer) value);
} else if(value instanceof String) {
putString((String) value);
}
throw new IllegalArgumentException("Illegal value = " + value);
}
public Object get(int index) {
boolean booleanValue = booleans.get(index);
if(booleanValue != booleans.getNoEntryValue()) {
return booleanValue;
}
int intValue = ints.get(index);
if(intValue != ints.getNoEntryValue()) {
return intValue;
}
String stringValue = strings.get(index);
if(stringValue != null) {
return stringValue;
}
return null;
}
请注意,这种方法只有在真正尝试优化内存占用量的情况下才会奏效,因为可以避免保留对装箱对象的引用的开销。 我认为您需要维护大量收藏品以衡量差异。 在实施此类集合之前,请确保检查应用程序的占用空间。
此方法对于列表的工作方式类似,其中对于每种原始类型,实现也将由映射支持,只是访问API会有所不同。 对于集合,您可以执行类似的操作,即通过TXXXSet
备份每个原始集合。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.