繁体   English   中英

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

[英]Java: Generic collection for holding primitives of different types

这可能是一个愚蠢的问题,但是Java中是否有一种类型的集合可以容纳不同类型的原语? 我当前正在创建一种格式化两种类型的对象的方法,并且尝试将参数存储在数组中,以避免使用带有十多个参数的方法,而是使用两个数组来保存值并将它们传递给它们。

类型将是字符串,整数和布尔值的组合。

Java中的基元可以装箱成对象。 通过将原始int值存储为Integer对象,并将原始boolean值存储为Boolean对象, Object类型可以保存Stringintboolean类型的值。 这通常可以隐式完成,而无需程序员显式包装或拆开它们,这称为自动装箱。

因此,任何保存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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM