相同的数组元素

时间:2014-03-19 05:19:24

标签: java arrays

我想检查一个数组中的所有元素是否与另一个数组中的所有元素相同,即一对一匹配。 (注意:两个数组元素的顺序不会相同)

有没有快速的方法,或者我可以使用预先存在的库?

目前我能想到的两种方式并不漂亮:

逐个匹配 (编辑3:此示例错误,不支持重复)

    boolean exactMatch = true;
    if(strList1.size() == strList2.size()){
        for(String str: StrList1){
            if(!strList2.contains(str)){
                exactMatch = false;
                break;
            }
        }
    }

排序然后匹配(更优化,大数组的esp)

    strList1 = Arrays.sort(strList1);
    strList2 = Arrays.sort(strList2);

    boolean exactMatch = true;
    if(strList1.size() == strList2.size()){
        for (int i = 0; i < strList1.length; i++) {
            if(!strList1[i].equals(strList2[i])){
                exactMatch = false;
                break;
            }
        }
    }

修改1

感谢那些发表评论的人。数组元素的顺序不同。即,以下将返回false:

String[] strList1 = {"ABC", "CDE", "EFG"};
String[] strList2 = {"ABC", "EFG", "CDE"};
System.out.println("array equals " + Arrays.deepEquals(strList1, strList2));

修改2

我遗漏的一个好处是'myusuf'指出的是数组中重复的问题。 这意味着我的“Match One By One”示例不起作用。以此为例:

public static void main(String[] args) {
    String[] strList1 = {"ABC", "CDE", "EFG", "ABC"};
    String[] strList2 = {"ABC", "EFG", "CDE", "CDE"};
    System.out.println(arrayEquals(strList1,strList2));
}
private static boolean arrayEquals(String[] array1, String[] array2) {
    List<String> list1 = Arrays.asList(array1);
    List<String> list2 = Arrays.asList(array2);
    return list1.containsAll(list2) && list2.containsAll(list1);
}

在这种情况下,strList1具有“ABC”的副本,而strList2具有“CDE”的副本,但它们仍然匹配,因为它们的唯一元素仍然相同,当它自己的数组不同时。


编辑3

感谢所有回答的人。 所以经过多次来回,似乎最简单的方法是:

    String[] strList1 = {"ABC", "CDE", "EFG", "CDE", "EFG"};
    String[] strList2 = {"ABC", "EFG", "CDE", "EFG", "CDE"};

    Arrays.sort(strList1);
    Arrays.sort(strList2);
    boolean exactMatch = Arrays.deepEquals(strList1, strList2);

    System.out.println("test3 - match: " + exactMatch);

我希望有一个可以完成所有操作的方法调用,但似乎已经完成了。 如果所有元素按顺序不同,则Arrays.deepEquals()仅适用于已排序的数组。 使用contains()的方法不起作用,因为有重复。

7 个答案:

答案 0 :(得分:1)

Arrays#deepEquals(java.lang.Object[], java.lang.Object[])

它提供了两个数组引用被认为是非常相等或不同。

Arrays.deepEquals(e1,e2);
  

如果有的话,两个可能为空的元素e1和e2非常相等   以下条件成立:

 - e1 and e2 are both arrays of object reference types, and
   Arrays.deepEquals(e1, e2) would return true
 - e1 and e2 are arrays of the same primitive type, and the appropriate
   overloading of Arrays.equals(e1, e2) would return true.
 - e1 == e2
 - e1.equals(e2) would return true.

Note that this definition permits null elements at any depth.

Documentation

Arrays#equals(Object[],Object[])方法不同,此方法适用于任意深度的嵌套数组。

答案 1 :(得分:1)

使用Arrays.equals

Arrays.equals(ary, ary2));

Arrays.deepEquals

  

如果两个指定的数组彼此非常相等,则返回true。与@link {#equals {Object [],Object [])方法不同,此方法适用于任意深度的嵌套数组。   如果两个数组引用都为null,或者它们引用包含相同数量元素的数组,并且两个数组中所有相应的元素对完全相等,则认为它们是完全相等的。

     

如果满足以下任何条件,则两个可能为空的元素e1和e2非常相等:

     

e1和e2都是对象引用类型的数组,Arrays.deepEquals(e1, e2)将返回true
  e1和e2是相同基元类型的数组,Arrays.equals(e1, e2)的适当重载将返回true
  e1 == e2
  e1.equals(e2)将返回true。

答案 2 :(得分:1)

public static boolean equals(int[] a, int[] a2)

如果两个指定的int数组彼此相等,则返回true。如果两个数组包含相同数量的元素,则两个数组被认为是相等的,并且两个数组中的所有相应元素对相等。换句话说,如果两个数组包含相同顺序的相同元素,则它们是相等的。此外,如果两个数组引用都为空,则认为它们相等。

答案 3 :(得分:1)

您可以使用列表removeAll方法

strList2.removeAll(strList1)

if(strList2.isEmpty)
{
  // Exact match
}
else{

  // failed
}

答案 4 :(得分:1)

您可以使用哈希地图。此方法具有较低的时间复杂度,因为不需要排序和搜索,但使用散列映射时空间复杂度更高:

        String[] strList1 = {"ABC", "CDE", "EFG"};
        String[] strList2 = {"ABC", "EFG", "CDE"};
        Boolean flag = true;
        Map<String, Integer> map = new HashMap<String, Integer>();

        /*Initial Check*/

        if(strList1.length != strList2.length) {
           System.out.print("Array equals: false");
           return 0;
        }

        /*Add all strings from list1 and their frequency to map*/

        for(int i=0; i<strList1.length;i++) {
            if(map.get(strList1[i]) != null) 
               map.put(strList1[i], map.get(strList1[i]) + 1);
            else
               map.put(strList1[i], 0); 
        }

        /*If string found in map from list2, decrement count in map
          else list2 contains a string not in map, then arrays 
          unequal as list2 contains a string not in list1*/

        for(int i=0; i<strList2.length;i++) {
            if(map.get(strList2[i]) != null)
               map.put(strList2[i], map.get(strList2[i]) - 1);
            else {  
                System.out.print("Array equals: false");
                flag = false;
            }
        }

        /*If map contains the same value for every string i.e. 0, then they occur
          equal no. of times in both arrays. Hence, Set values will contain 
          only one value so (values.size() == 1) will be equal true, else false*/

        if(flag) {
            Set<Integer> values = new HashSet<Integer>(map.values());
            System.out.print("Array equals: " + (values.size() == 1));
        }
        return 0;

对于您的输入,这将输出:Array equals: true
此方法还考虑输入数组中的重复字符串。

答案 5 :(得分:1)

这可能是您问题的简短解决方案。我确信有更多高性能但复杂的方法可以做到这一点。这里arrayEquals会将您的数组转换为List并使用List.containsAll来检查相等性。

public class ArrayEquality {
    public static void main(String[] args) {
        String[] array1 = {"test1","test2"};
        String[] array2 = {"test2","test1"};
        String[] array3 = {"test2","test3"};

        String[] strList1 = {"ABC", "CDE", "EFG"};
        String[] strList2 = {"ABC", "EFG", "CDE"};

        System.out.println(arrayEquals(array1,array2));
        System.out.println(arrayEquals(array2,array3));

        System.out.println(arrayEquals(strList1,strList2));
    }

    //ARRAY EQUALITY CHECK
    private static boolean arrayEquals(String[] array1, String[] array2) {
        List<String> list1 = Arrays.asList(array1);
        List<String> list2 = Arrays.asList(array2);

        return list1.containsAll(list2) && list2.containsAll(list1);
    }
}

要处理此解决方案中的重复项,可以像这样更改

private static boolean arrayEquals(String[] array1, String[] array2) {
List<String> list1 = Arrays.asList(array1);
List<String> list2 = Arrays.asList(array2);

Collections.sort (list1);
Collections.sort (list2);
return list1.equals(list2);
}

可以通过大小检查来优化它以避免排序。

答案 6 :(得分:1)

您可以使用以下内容:

String[] strArray1;
String[] strArray2;

我将其重命名为strArray而不是strList以获得逻辑性,然后:

private <T> boolean containsAll(final T[] a1, final T[] a2) {
    return Arrays.asList(a1).containsAll(Arrays.asList(a2));
}

并将其命名为:

boolean exactMath = containsAll(strArray1, strArray2) 
        && containsAll(strArray2, strArray1);

请注意,Arrays.asList(T[] array)只是在List<T>附近创建T[] array 包装,它实际上并不复制T[] array。如果您修改List<T>,则修改支持T[] array