簡體   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