"no primitives in container" 规则是否适用于数组?
Does the "no primitives in container" rule apply to arrays?
我最近一直在尝试实现一个简单的遗传算法。我需要使用存储 (Character,4 bits)
对的可逆映射。我为此任务选择了 Guava 的 BiMap
。但是,由于我为位存储选择了 int
数组,因此测试不会通过。
int[]
是原始类型吗?使用 Vector
或 List
整数是否更适合此任务?
Is int[]
primitive type?
没有。 Java 数组不是原始类型,即使它们的单个元素是原始类型也是如此。
Will using vector or list of integers be appropriate tool for such task?
Vector<T>
和 List<T>
都无法在没有 "boxing" 的情况下将原语存储到包装器中。但是,如果您只需要四位,则可以使用一个 byte
,它有八位可用于存储。
要从 byte
中提取位 k
,请使用 (b & (1 << k)) != 0
表达式。当此表达式的计算结果为 true
时,位 k
设置为 1
;否则,它被设置为 0
.
要将字节中的位 k
设置为 1
,请使用 b |= (1 << k)
。要将位 k
重置为 0
,请使用 b &= ~(1 << k)
你的问题不在于 int[]
是原始的。 Java 中的数组是一个对象。问题是它是一个对象 ,它不会覆盖 hashCode()
和 equals()
方法。
因为它没有覆盖它们,所以它们与 Object 的相同,其中对象只有在相同(即对同一实例的引用)时才相等。
基本上:
int[] a = new int[] {1,1,1,1};
int[] b = new int[] {1,1,1,1};
System.out.println( a.equals(b) );
你可能期望它打印 true
,但它会打印 false
,因为你创建了两个不同的数组,它检查数组是否是同一个对象,而不是它们的内容是否相同是一样的!
很有可能,如果您还添加
System.out.println( a.hashCode() );
System.out.println( b.hashCode() );
您还将获得两个不同的哈希码。
因此,数组不太适合用于检查 equality/uniqueness 的集合。它们与标准 Map
中的 value 一样好,但不如 key。在 Guava BiMap
中,它们既不能用作键也不能用作值。
你应该怎么做?
您应该使用覆盖 equals()
和 hashCode()
的对象,这样如果内容相同,equals()
returns true
和两者从 hashCode()
返回相同的值。
如果你想要相对紧凑的东西,你可以用 Byte
对象来表示这些位。您可以使用位操作运算符。
或者您可以使用 BitSet
,它是 Java 位的标准容器。
小心,因为 BitSet
是可变的。可变对象在哈希表等对值敏感的数据结构中使用时可能表现不佳,因为大多数实现无法判断您何时更改了值,因此它们无法相应地在哈希桶中移动它。一旦对象存储在 BiMap
!
中,不要设置或清除对象中的任何位
我最近一直在尝试实现一个简单的遗传算法。我需要使用存储 (Character,4 bits)
对的可逆映射。我为此任务选择了 Guava 的 BiMap
。但是,由于我为位存储选择了 int
数组,因此测试不会通过。
int[]
是原始类型吗?使用 Vector
或 List
整数是否更适合此任务?
Is
int[]
primitive type?
没有。 Java 数组不是原始类型,即使它们的单个元素是原始类型也是如此。
Will using vector or list of integers be appropriate tool for such task?
Vector<T>
和 List<T>
都无法在没有 "boxing" 的情况下将原语存储到包装器中。但是,如果您只需要四位,则可以使用一个 byte
,它有八位可用于存储。
要从 byte
中提取位 k
,请使用 (b & (1 << k)) != 0
表达式。当此表达式的计算结果为 true
时,位 k
设置为 1
;否则,它被设置为 0
.
要将字节中的位 k
设置为 1
,请使用 b |= (1 << k)
。要将位 k
重置为 0
,请使用 b &= ~(1 << k)
你的问题不在于 int[]
是原始的。 Java 中的数组是一个对象。问题是它是一个对象 ,它不会覆盖 hashCode()
和 equals()
方法。
因为它没有覆盖它们,所以它们与 Object 的相同,其中对象只有在相同(即对同一实例的引用)时才相等。
基本上:
int[] a = new int[] {1,1,1,1};
int[] b = new int[] {1,1,1,1};
System.out.println( a.equals(b) );
你可能期望它打印 true
,但它会打印 false
,因为你创建了两个不同的数组,它检查数组是否是同一个对象,而不是它们的内容是否相同是一样的!
很有可能,如果您还添加
System.out.println( a.hashCode() );
System.out.println( b.hashCode() );
您还将获得两个不同的哈希码。
因此,数组不太适合用于检查 equality/uniqueness 的集合。它们与标准 Map
中的 value 一样好,但不如 key。在 Guava BiMap
中,它们既不能用作键也不能用作值。
你应该怎么做?
您应该使用覆盖 equals()
和 hashCode()
的对象,这样如果内容相同,equals()
returns true
和两者从 hashCode()
返回相同的值。
如果你想要相对紧凑的东西,你可以用 Byte
对象来表示这些位。您可以使用位操作运算符。
或者您可以使用 BitSet
,它是 Java 位的标准容器。
小心,因为 BitSet
是可变的。可变对象在哈希表等对值敏感的数据结构中使用时可能表现不佳,因为大多数实现无法判断您何时更改了值,因此它们无法相应地在哈希桶中移动它。一旦对象存储在 BiMap
!