Java:用于保存不同类型原语的通用集合

Java:用于保存不同类型原语的通用集合,java,generics,collections,Java,Generics,Collections,这可能是一个愚蠢的问题,但Java中是否有一种类型的集合可以容纳不同类型的原语?我目前正在创建一个格式化两种类型对象的方法,并尝试将参数存储在数组中,以避免使用一个包含10个以上参数的方法,而是使用两个数组来保存值并将其传入 类型将是字符串、int和boolean的组合。在Java中,唯一可以保存整数的“集合”是数组,它只能保存单一类型的原语 如果需要收集多个类型的基元,可以创建一个具有多个基元成员的类,然后使用任何要存储该类的多个实例的集合。Java中唯一可以保存整数的“集合”是数组,它只能保

这可能是一个愚蠢的问题,但Java中是否有一种类型的集合可以容纳不同类型的原语?我目前正在创建一个格式化两种类型对象的方法,并尝试将参数存储在数组中,以避免使用一个包含10个以上参数的方法,而是使用两个数组来保存值并将其传入

类型将是字符串、int和boolean的组合。

在Java中,唯一可以保存整数的“集合”是数组,它只能保存单一类型的原语

如果需要收集多个类型的基元,可以创建一个具有多个基元成员的类,然后使用任何要存储该类的多个实例的集合。

Java中唯一可以保存整数的“集合”是数组,它只能保存单个类型的基元


如果需要收集多种类型的基元,可以创建一个具有多个基元成员的类,然后使用任何要存储该类的多个实例的集合。

Java中的基元可以装箱到对象中。类型
对象
可以保存类型
字符串
int
布尔
的值,方法是将基元
int
值存储为
整数
对象,将基元
布尔
值存储为
布尔
对象。这通常可以隐式地完成,而无需程序员显式地包装或展开它们,这称为自动装箱

因此,任何保存类型为
Object
的值的集合或数组,例如
Object[]
List
等,都可以保存您的值

例如:

Object[] array = new Object[] { 1, 2, true, "hi" };

List<Object> list = new ArrayList<Object>();
list.add(5);
list.add(false);
list.add("test");
处理
对象的数组或集合时,可以使用
instanceof
和强制转换来查找类型并正确处理它们

警告 当自动装箱以键入
对象
时,原语直接装箱到
对象
值中。在以下代码中:

short shortValue = 0;
int myPrimitive = shortValue;
Object myObject = shortValue;
myPrimitive
的类型为
int
,但
myObject
的类型为
Short
。你要了一个
对象,你得到了一个!请注意您对
对象
类型的对象的假设,因为原则上,您不能假设它是
对象

幸运的是,您不必总是为每个基本数字类型检查
对象。在大多数情况下,将其转换为
数字
,然后使用例如
.intValue()
来获取int类型的值就足够了。也就是说,代码如下:

double x = 2.3;
Object o = x;
int i = ((Number) o).intValue();
相当于:

double x = 2.3;
int i = (int) x;

Java中的原语可以装箱到对象中。类型
对象
可以保存类型
字符串
int
布尔
的值,方法是将基元
int
值存储为
整数
对象,将基元
布尔
值存储为
布尔
对象。这通常可以隐式地完成,而无需程序员显式地包装或展开它们,这称为自动装箱

因此,任何保存类型为
Object
的值的集合或数组,例如
Object[]
List
等,都可以保存您的值

例如:

Object[] array = new Object[] { 1, 2, true, "hi" };

List<Object> list = new ArrayList<Object>();
list.add(5);
list.add(false);
list.add("test");
处理
对象的数组或集合时,可以使用
instanceof
和强制转换来查找类型并正确处理它们

警告 当自动装箱以键入
对象
时,原语直接装箱到
对象
值中。在以下代码中:

short shortValue = 0;
int myPrimitive = shortValue;
Object myObject = shortValue;
myPrimitive
的类型为
int
,但
myObject
的类型为
Short
。你要了一个
对象,你得到了一个!请注意您对
对象
类型的对象的假设,因为原则上,您不能假设它是
对象

幸运的是,您不必总是为每个基本数字类型检查
对象。在大多数情况下,将其转换为
数字
,然后使用例如
.intValue()
来获取int类型的值就足够了。也就是说,代码如下:

double x = 2.3;
Object o = x;
int i = ((Number) o).intValue();
相当于:

double x = 2.3;
int i = (int) x;

假设您确实需要这样一个集合,以避免为值装箱的成本,那么您可以借助已经实现的原语集合轻松地实现这样一个集合。由于您没有指定所需的集合类型,让我们看一个将原始整数映射到您指定的值的示例映射:

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);
  }
}
请注意,这种方法只有在您真正尝试优化内存占用时才有回报,因为这样可以避免保留对装箱对象的引用的开销。我假设您需要维护大量的集合来衡量差异。在实现这样的集合之前,请确保检查应用程序的占用空间


这种方法同样适用于列表,在这些列表中,实现还将由每个基元类型的映射支持,只是访问API不同。对于集合,可以执行类似的操作,即通过
txxset
备份每个基元集合

假设您确实需要这样一个集合,以避免为值装箱的成本,那么您可以借助已经实现的原语集合轻松实现这样一个集合。由于您没有指定所需的集合类型,让我们看一个将原始整数映射到您指定的值的示例映射:

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);
  }
}
请注意,这种方法只有在您真正尝试优化内存占用时才有回报,因为这样可以避免保留对装箱对象的引用的开销。我假设您需要维护大量的集合来衡量差异。请务必检查您的应用程序