簡體   English   中英

Java比較無序的ArrayLists

[英]Java compare unordered ArrayLists

任何人都知道一種有效的方法來決定兩個arraylists是否包含相同的值?

碼:

ArrayList<String> dummy1= new ArrayList<String>();
list1.put("foo");
list1.put("baa");

ArrayList<String> dummy2= new ArrayList<String>();
list1.put("baa");
list1.put("foo");

dummy1 == dummy2

挑戰在於,arraylists沒有相同的價值秩序。

(foo, baa) == (foo, baa) // per definition :)

我需要得到這個

(foo, baa) == (baa, foo) // true

那么你的方法是什么?

先排序吧。

public  boolean equalLists(List<String> one, List<String> two){     
    if (one == null && two == null){
        return true;
    }

    if((one == null && two != null) 
      || one != null && two == null
      || one.size() != two.size()){
        return false;
    }

    //to avoid messing the order of the lists we will use a copy
    //as noted in comments by A. R. S.
    one = new ArrayList<String>(one); 
    two = new ArrayList<String>(two);   

    Collections.sort(one);
    Collections.sort(two);      
    return one.equals(two);
}

老實說,你應該檢查你的數據結構決定。 這似乎更像是一個問題。 排序然后比較將采用O(nlog n),而HashSet比較將僅為O(n)。

sort方法在O(n log n)中運行,但我們可以做得更好。 首先執行空值和大小比較。 然后使用HashMap<String, Integer>並將特定字符串的頻率存儲為值。 對其中一個列表執行此操作,然后迭代另一個列表並檢查映射是否包含字符串並具有相同的頻率。 該方法是O(n)。

假設列表不包含重復項,您可以使用兩個臨時HashSet<String>對象。

從您正在比較的ArrayList<String>構造String的集合,然后檢查第一個集合是否包含第二個列表中的所有項目,第二個集合包含第一個列表中的所有項目。

你可以這樣做:

List<String> a = ...;
List<String> b = ...;
Set<String> setA = new HashSet<String>(a);
Set<String> setB = new HashSet<String>(b);
boolean same = setA.containsAll(b) && setB.containsAll(a);

如果必須考慮重復項,請將HashSet<String>替換為HashMap<String,Integer>以生成並比較相應的頻率計數器。

您應該對兩個ArrayLists進行排序,然后進行相同的比較。 但是,您可能需要刪除重復項(我不確定您的重復項策略)。

最有效的方法取決於陣列的大小。

  • 對於非常小的列表,使用contains()可能是最有效的。 (也許對於0到5個元素的列表......我猜。)

  • 對於中型到大型列表,您可以:

    • 對兩個數組列表進行排序並將它們成對比較,

    • 排序一個列表並使用二進制搜索來探測第二個列表中的值。

    • 將一個轉換為HashSet並使用第二個中的值進行探測。

復雜性分析不是直截了當的,因為它取決於列表是否相等的可能性。 “最壞的情況”是列表相等時,因為這意味着您必須先檢查所有元素,然后才能返回true 在那種情況下,復雜性分別是O(N^2)O(NlogN)O(NlogN)O(N)

這沒有考慮到空間使用,並且(在Java中)使用大量內存對性能的影響,

還存在“比例常數”的問題; 例如,對於小的N值, O(NlogN)可以比O(N)快。

簡而言之......沒有一種解決方案永遠是最好的。

這里有Java 8,請指定是否需要Java 7解決方案。

假設1: ArrayList不是空值。

其時間復雜度為O(N),其中N是任何輸入的大小。

除輸入外,其內存復雜度為0(N)

換句話說,它的時間和內存復雜性是線性的。

從理論上講,你可以有一個恆定的O(1)內存復雜性,但它會涉及從a1刪除元素,同時將它們添加到setA1 在我看來,這對垃圾收集器太過依賴,所以希望這個解決方案對你來說已經足夠了。

import java.util.*;

public class ArraySameValuesSolver {

    public boolean of(List<String> list1, List<String> list2) {
        if (list1.size() != list2.size())
            return false;
        Map<String, Integer> occ = new HashMap<>();
        list1.stream().forEach(s -> incrementOccurences(occ, s));
        for (String s: list2) {
            decrementOccurrences(occ, s);
            if (occ.get(s) < 0)
                return false;
        }
        return true;
    }

    private void incrementOccurences(Map<String, Integer> occ, String s) {
        if (!occ.containsKey(s))
            occ.put(s, 1);
        else
            occ.put(s, occ.get(s) + 1);
    }

    private void decrementOccurrences(Map<String, Integer> occ, String s) {
        if (!occ.containsKey(s))
            occ.put(s, -1);
        else
            occ.put(s, occ.get(s) - 1);
    }

}
  public boolean isListEquals( List listA , List listB ) {
    boolean result = false;

    if ( ( listA == listB ) ) {
      result = true;
      return result;
    }

    if ( ( listA == null ) || ( listB == null ) ) {
      return result;
    }

    if ( listA.size() != listB.size() ) {
      return result;
    }

    List listC = new ArrayList( listA );
    listC.removeAll( listB );
    if ( listC.size() > 0 ) {
      return result;
    }

    result = true;
    return result;
  }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM