繁体   English   中英

Java:如何确保基于列表中的值存储唯一数组

[英]Java: How to be sure to store unique arrays based on its values on a List

我有许多Object []的一维数组(如果有帮助,这些对象是原始类型)

我想将这些数组存储在一个列表中,但是仅将其内容与其他数组唯一的数组存储。

我的第一个替代方法是遍历存储在Set中的数组Arrays.hashCode(array)的值,并且仅在该值未在集合中合并的情况下才将数组存储在所需的列表中。

但是后来我意识到具有不同内容的两个数组可以产生相同的哈希码(我希望不是很频繁)

有人可以帮忙吗?

我可以期待非常频繁的哈希码冲突(来自不同内容的相同hascode)吗?

问题是您将拥有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 列表具有一致的equalshashCode方法。 如果两个列表包含相同顺序的相同元素,则两个列表定义为相等 ,并且列表的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()方法描述:

如果两个数组包含相同顺序的相同元素,则它们相等。

为了进行有效的比较,有时使用两步法:

  1. hashCode丢弃许多潜在的匹配项
  2. 如果两个hashCode相等,则对对象本身进行相等性测试(取决于其方法equals

关于您的Object[]具有原始类型,请记住以下几点:
要将原始类型添​​加到Object[] ,将始终将其装箱/拆箱
因此,您实际上并没有原始类型作为数组的内容。

为了保留基本类型,数组本身必须是基本类型,例如int[]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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