我有许多 Object[] 的一维数组(如果有帮助,这些对象是原始类型)
我想将这些数组存储在一个列表中,但只有其内容与其他数组不同的数组。
我的第一个近似值是遍历存储在 Set 中的数组 Arrays.hashCode(array) 的值,并且如果该值未包含在集合中,则仅将数组存储在所需的列表中。
但后来我意识到两个具有不同内容的数组可以产生相同的哈希码(我希望不经常)
谁能帮忙?
我可以期待非常频繁的哈希码冲突(来自不同内容的相同哈希码)吗?
问题是您将拥有 arrayX 和 arrayY,两者都具有内容 [a,b,c] 但 Set 不将它们视为平等?[a,b,c] 和 [c,a,b] 是否会被视为相等?
我会说定义一个比较器,它为数组定义“相等”,正是你需要它定义的方式,然后将每个数组插入到使用你创建的自定义比较器的 Set 中。
听起来您需要一个 LinkedHashSet (在保持唯一性的同时保留插入顺序),然后将数组包装在一个对象中,该对象以对数组有意义的方式实现哈希码和相等。第一个近似值可能只是 Arrays.asList() 方法,但您在问题中声明您在 Object[] 数组中使用原语。要么您依赖自动装箱,要么您实际上没有使用 Object[] 数组,而是根据需要使用 int[]、long[]、float[]。Arrays.asList() 无法与这些类型一起正常工作。
编辑:根据评论的要求,这里是包装类的代码:
public class ArrayWrapper {
private Object[]array;
public ArrayWrapper(Object[] array) { this.array = array; }
public Object[] getArray() {
Object[] newArray=new Object[array.length];
System.arraycopy(array,0,newArray,0,array.length);
return newArray;
}
public int hashCode() { return Arrays.hashCode(array); }
public boolean equals(Object obj) {
boolean b=false;
if(obj instanceof ArrayWrapper){
b=Arrays.equals(this.array,((ArrayWrapper)obj).getArray());
}
return b;
}
}
如果哈希码相同,那么您只需进一步检查其详细信息。
以下假设您认为数组 {1,2,3} 和 {3,2,1} 不重复。
不要将数组的哈希码存储到 Set,将整个列表存储到 Set。
将您的数组转换为List。列表具有一致的equals和hashCode方法。如果两个列表包含相同顺序的相同元素,则定义为相等,并且列表的 hashCode 将与 equals 方法一致。
List<Object> list = Arrays.asList(array);
这是整个算法。(未经测试的代码,但应该可以工作)。
Set<List<Object>> findUniqueLists(List<List<Object>> allLists) {
Set<List<Object>> uniqueSet = new LinkedHashSet<List<Object>>();
uniqueSet.addAll(allLists);
Set<List<Object>> processedSet = new LinkedHashSet<List<Object>>();
for(List<Object> list : allLists) {
if(processedSet.contains(list)) {
// duplicate found!
uniqueSet.remove(list);
} else {
// no duplicate
processedSet.add(list)
}
}
return uniqueSet;
}
尝试这样的事情:
编辑
运行和工作代码如下:
bash-3.2$ cat ArraysTest.java
import java.util.*;
public class ArraysTest {
public static void main( String [] args ) {
Set<Integer[]> set = new TreeSet<Integer[]>( new Comparator<Integer[]>() {
public int compare( Integer[] one, Integer[] two ) {
if( Arrays.equals( one, two ) ) {
return 0;
}
return Arrays.hashCode( one ) - Arrays.hashCode( two );
}
public boolean equals( Object o ){ return false; }
});
set.add( new Integer[]{1,2,3});
set.add( new Integer[]{1,2,3});
set.add( new Integer[]{3,2,1});
for( Integer[] i : set ) {
System.out.println( Arrays.asList( i ) );
}
}
}
bash-3.2$ javac ArraysTest.java
bash-3.2$ java ArraysTest
[1, 2, 3]
[3, 2, 1]
bash-3.2$
您必须做一些工作才能使其正常工作,这只是一个示例,而不是实际运行的代码。
如您所知, Set 只接受一个元素,并且TreeSet
使用自定义比较器创建它可以让您告诉 set 什么对您来说是相等的。
Arrays.equals()
方法描述:
..如果两个数组以相同的顺序包含相同的元素,则它们相等...
为了有效地比较,有时使用两步方法:
hashCode
丢弃许多潜在的匹配项equals
)关于您Object[]
是原始类型,请记住以下几点:
要将原始类型添加到 中Object[]
,它将始终被装箱/取消装箱。
因此,您实际上并没有原始类型作为数组的内容。
为了保留原始类型,数组本身必须是原始类型,例如int[]
.