JackDev
JackDev

Reputation: 11173

Same Array Elements

I want to check if all the elements in one array is the same as all the elements in another array, ie, one to one match. (NB: the two array elements will not be in the same order as each other)

Is there a quick way of doing this, or a pre-existing library I can use?

Currently the two ways I can think of is not pretty:

match one by one (Edit 3: this example is wrong, doesn't cater for duplicates)

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

sort then match (more optimised, esp for large arrays)

    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;
            }
        }
    }

Edit 1

Thanks for those who has given comments. The array elements are not in the same order as each other. ie, the following will return false:

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

Edit 2

One good point I left out which 'myusuf' pointed out is the matter of duplicates in the array. This means that my "Match One By One" example will not work. Take this for example:

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);
}

In this case, strList1 has a duplicate for "ABC" and strList2 has a duplicate for "CDE", but they still match because their unique elements are still the same, when the array it self is different.


Edit 3

Thanks everyone that have answered. So after a lot of back and forth, it seems the shortest way to do it is:

    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);

I was hoping for one method call that could do it all, but it seems there is done. Arrays.deepEquals() only works with sorted arrays if all elements are different in order. The approach with contains() does not work as there are duplicates.

Upvotes: 1

Views: 455

Answers (7)

Sumit Singh
Sumit Singh

Reputation: 15886

Use Arrays.equals:

Arrays.equals(ary, ary2));

Or Arrays.deepEquals

Returns true if the two specified arrays are deeply equal to one another. Unlike the @link{#equals{Object[],Object[]) method, this method is appropriate for use with nested arrays of arbitrary depth.

Two array references are considered deeply equal if both are null, or if they refer to arrays that contain the same number of elements and all corresponding pairs of elements in the two arrays are deeply equal.

Two possibly null elements e1 and e2 are deeply equal if any of the following conditions hold:

  • 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.

Upvotes: 1

wumpz
wumpz

Reputation: 9131

This would be a short solution of your problem. I am sure there are more performant but complicated methods to do it. Here arrayEquals transforms your arrays into a List and uses List.containsAll to check equality.

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);
    }
}

To deal with duplicates within this solution arrayEquals could be changed like this

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);
}

One could optimise it by size checking to avoid sorting.

Upvotes: 1

skiwi
skiwi

Reputation: 69259

You can use the following for this:

String[] strArray1;
String[] strArray2;

I renamed them to strArray instead of strList for logicalness, then:

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

and call it with:

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

Please note that Arrays.asList(T[] array) just creates a List<T> wrapper around the T[] array, it does not actually make a copy of T[] array. If you modify the List<T>, it will also modify the backing T[] array.

Upvotes: 1

myusuf
myusuf

Reputation: 12240

You could use a hash Map. This method has lower time complexity as no sorting and searching is required, but higher space complexity as hash map is used:

        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;

For your input, this would output: Array equals: true.
This method also takes into account duplicate strings in input arrays.

Upvotes: 1

Siva
Siva

Reputation: 1940

You can use list removeAll method

strList2.removeAll(strList1)

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

  // failed
}

Upvotes: 1

Dineshkumar
Dineshkumar

Reputation: 4245

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

Returns true if the two specified arrays of ints are equal to one another. Two arrays are considered equal if both arrays contain the same number of elements, and all corresponding pairs of elements in the two arrays are equal. In other words, two arrays are equal if they contain the same elements in the same order. Also, two array references are considered equal if both are null.

Upvotes: 1

Subhrajyoti Majumder
Subhrajyoti Majumder

Reputation: 41200

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

It provides the two array references are considered deeply equal or not.

Arrays.deepEquals(e1,e2);

Two possibly null elements e1 and e2 are deeply equal if any of the following conditions hold:

 - 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

Unlike the Arrays#equals(Object[],Object[]) method, this method is appropriate for use with nested arrays of arbitrary depth.

Upvotes: 1

Related Questions