Isabel Jinson
Isabel Jinson

Reputation: 8671

compare string array using collection

I have two String arrays a,b.

String a [] = {"one","two","three"};
String b [] = {"one","Two","Three","four"};

I need to check whether both arrays are same or not , with case Insensitive . I know , the following piece of code is perfect for case sensitive.

List <String> l1 = Arrays.asList(a);
List <String> l2 = Arrays.asList(b);
System.out.println(l2.containsAll(l1));  

Is there any other way to compare two string array (case Insensitive ) using collection?

Upvotes: 4

Views: 9712

Answers (8)

Isabel Jinson
Isabel Jinson

Reputation: 8671

Using one for loop -

String [] oldVal = {"one","two","three","Four"};
String [] newVal = {"one","Two","Three","four"};


if(oldVal.length == newVal.length)
{
 //
 for(int y =0; y<oldVal.length; y++)
 {
  oldVal[y] = oldVal[y].toUpperCase();
  newVal[y] = newVal[y].toUpperCase();
 }

 return Arrays.asList(oldVal).containsAll(Arrays.asList(newVal));

}
 return false;  

Upvotes: 0

polygenelubricants
polygenelubricants

Reputation: 384016

If the arrays don't contain duplicates, one way to do this in O(N) is to use a Set that represents a canonical form of the strings in the array. Something like this:

static Set<String> canonicalSet(String[] arr) {
    Set<String> upperSet = new HashSet<String>();
    for (String s : arr) {
        upperSet.add(s.toUpperCase());
    }
    return upperSet;
}
static boolean equalsCanonically(String[] arr1, String[] arr2) {
    return canonicalSet(arr1).equals(canonicalSet(arr2));
}

This is time-optimal.

You can also do variations on this technique to save more space, e.g. instead of constructing the canonical sets and comparing them, you can construct the canonical set for arr1, and then remove entries from that set according to elements of arr2. It the set is empty afterward, and you can always find what you need to remove, the two arrays are canonically equal.

static boolean equalsCanonically2(String[] arr1, String[] arr2) {
    Set<String> canon = canonicalSet(arr1);
    for (String s : arr2) {
        if (!canon.remove(s.toUpperCase())) return false;
    }
    return canon.isEmpty();
}

You can also do a simple size-comparison check if you think it's worth it (i.e. if often the two arrays don't even have the same number of elements).

If there are duplicates in the arrays, then the Set method will not work as is. You'd need a multiset, and you can either implement your own, or use Google Collections'.


There are also O(N log N) ways to do this involving sorting the strings. You can sort both arrays and then do a simple linear check. A case-insensitive comparator must be used, and in fact it's already there as String.CASE_INSENSITIVE_ORDER.

static boolean equalsCanonically3(String[] arr1, String[] arr2) {
    int N = arr1.length;
    if (arr2.length != N) return false;
    Arrays.sort(arr1, String.CASE_INSENSITIVE_ORDER);
    Arrays.sort(arr2, String.CASE_INSENSITIVE_ORDER);
    for (int i = 0; i < N; i++) {
        if (String.CASE_INSENSITIVE_ORDER.compare(arr1[i], arr2[i]) != 0) {
            return false;
        }
    }
    return true;
}

This last technique works even if the arrays contain duplicates. It does it O(N log N). It sorts the arrays passed as parameters, so if the original state is important, you want to pass their clone() instead.

Upvotes: 1

Isabel Jinson
Isabel Jinson

Reputation: 8671

Finally , I used TreeSet with case insensitive comparator.

Example :

 String [] oldVal = {"one","two","three","Four"};
 String [] newVal = {"one","Two","Three","four"};

 Set <String> set1 = new TreeSet <String> (String.CASE_INSENSITIVE_ORDER);
 Set <String> set2 = new TreeSet <String> (String.CASE_INSENSITIVE_ORDER);

 set1.addAll(Arrays.asList(oldVal));
 set2.addAll(Arrays.asList(newVal));

 System.out.println("--Using Tree Set --- "+ set1.containsAll(set2));  // Return True

Thanks Guys..

Upvotes: 4

fastcodejava
fastcodejava

Reputation: 41127

You could first check if their lengths are equal. Then you could put items of a in HashMap and go over b and check if the items are there.

Upvotes: 0

JRL
JRL

Reputation: 78033

You could use a TreeMap with a case-insensitive comparator.

Upvotes: 1

CPerkins
CPerkins

Reputation: 9018

Your sample data are sorted. If this is guaranteed to be the case in reality, you should do as Andrey says, and use nested loops on the arrays themselves, breaking if/when you find an inequal pair of entries.

If they're not guaranteed to be sorted, I'd dump each of them into a HashSet, and then you can use java's Set containsAll method.

Edit: As Thomman pointed out, containsAll() ultimately relies on equals(). So in order to get the case-insensitive checking your question requests, you have two choices:

1) Upcase or downcase the strings on insertion into the sets. On consideration, I'm not crazy about this method, since not only will you lose duplicate entries, but you'll also fold entries differentiated by case. And so these lists would look to be equal to each other:


String a [] = {"one","one","one", "Two"};
String b [] = {"One", Two"};

2) The other choice is to put your strings into holder objects which override equals(), doing comparison in a case-insensitive way.

Upvotes: 0

JonH
JonH

Reputation: 33183

Couldn't you just loop it or use some sort of linq (Sorry just noticed this was java you cant use linq...?)

    List<string> matches = new List<string>();
    bool isSame=true;

    foreach(string s1 in l1)
     {
      foreach(string s2 in l2)
        {
         if(s1.ToLower() == s2.ToLower()) 
          matches.Add(s1);
         else
            {
             isSame=false;
             break;
            }
        }
       if (isSame) 
            continue;           
       else
            break;
     }

if (isSame)
    Console.Writeline("They are the same")
else
    Console.Writeline("Not the same");

You may want to check the count as I did not add that to the code, for instance l1.count > l2.count (in this case you know whether or not they are the same by the number of elements in the list). Simple test before even looping:

if (l1.Count != l2.Count) {
 //don't even bother looping
 //display no matches
}
else {
 //place rest of code here since l1.count = l2.count
}
  • CRAP DIDN'T REALIZE THIS WAS FOR JAVA THOUGHT IT WAS FOR C#. APPLY SAME LOGIC TO JAVA THOUGH...

Upvotes: 1

Andrey
Andrey

Reputation: 60115

check it in nested loops if you want custom comparison. or if you have large sets of data it might be cheaper to sort arrays first

Upvotes: 0

Related Questions