views:

212

answers:

6

In my Java application i need to compare two list's element whether it is similar or not.

In short suppose i have two list declared like shown below

List<String> a = new ArrayList<String>();
    a.add("one");
    a.add("three");
    a.add("two");
Collections.sort(a);


List<String> a1 = new ArrayList<String>();
    a1.add("ONE");
    a1.add("two");
    a1.add("THREE");
Collections.sort(a);

If i write a condition for equality it fails as some of list's element is in different case like

if(a.equals(a1)){
    System.out.println("equal");
} else{
    System.out.println("not equal");
}

It will display result "Not equal"

So please tell me how i can make the list element case-insensitive in Java language only.

Thank and regard

+6  A: 

You'd have to do that manually:

public boolean equalsIgnoreCase(List<String> l1, List<String> l2) {
  if (l1.size() != l2.size()) {
    return false;
  }
  Iterator<String> i1=l1.iterator();
  Iterator<String> i2=l2.iterator();
  while(i1.hasNext()) {
    if (!i1.next().equalsIgnoreCase(i2.next()) {
      return false;
    }
  }
  return true;
}
Joachim Sauer
oops, stupid typo, thanks gizmo ;-)
Joachim Sauer
+9  A: 

You need to use

Collections.sort(a, String.CASE_INSENSITIVE_ORDER);

in order to sort ignoring case, you can use the equalsIgnoreCase method on String to compare to values

You can of course create your own CaseInsensitiveList class, we have a CaseInsensitiveSet & CaseInsensitiveMap in our codebase

Jon Freedman
That's not a complete solution (neither is my post below ;-)).
Joachim Sauer
As Joachim says, this will **not** make `a.equals(a1)` return true.
Andrzej Doyle
Yes, I posted a little too soon, I've edited my original answer
Jon Freedman
sort only would be needed if original order does NOT matter.
Carlos Heuberger
A: 

You will need to override the equals() method on the list so it does what you want. Have a look at the current ArrayList.equals() and adapt it so it compares with equalsIgnoreCase instead of equals().

Thorbjørn Ravn Andersen
Or you make it take a comparator as a constructor argument. But the problem is that both of these violate the contract for `Collection` and this could cause things to not work as expected.
Stephen C
+4  A: 

You can also wrap your String into a helper class and implement the equals & compare methods for it.

public class StringWrapper implements Comparable<StringWrapper> {
    private String value;

    StringWrapper(Strig value) {
        this.value = value;
    }

    @Override boolean equals(Object o) {
        returns String.CASE_INSENSITIVE_ORDER.equals(
            (StringWrapper) o).value
            this.value);
    }

    @Override int compareTo(StringWrapper sw) {
        returns String.CASE_INSENSITIVE_ORDER.compare(
            this.value
            sw.value);        
    }

    @Override String toString() {
        return this.value;
    }

    @Override int hashCode() {
        return this.value.toLowerCase.hashCode();
    }
}

And then :

List<StringWrapper> a = new ArrayList<StringWrapper>();
    a.add(StringWrapper("one"));
    a.add(StringWrapper("TWO"));
    a.add(StringWrapper("three"));
Collections.sort(a);
Raphael Jolivet
You should implement `Comparable<StringWrapper>`, and change the `compare(Object)` method `compareTo(StringWrapper)`. You should also implement `hashCode()`, which might get tricky.
Joachim Sauer
(The StringWrapper needs to implement the `Comparable` interface - otherwise the `Collections.sort` causes a compile time error)
Andreas_D
this is definitely the way to go (+1)
seanizer
Thanks for the comments : answer edited accordingly.
Raphael Jolivet
+3  A: 

Why not using instead a SortedSet with a case insensitive comparator ? With the String.CASE_INSENSITIVE_ORDER comparator

Your code is reduced to

Set<String> a = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
    a.add("one");
    a.add("three");
    a.add("two");


Set<String> a1 = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
    a1.add("ONE");
    a1.add("two");
    a1.add("THREE");

And your equals conditions should work without any issue

EDIT modified according to comments. Thanks to all of you to correct me.

Riduidel
(you have to use a different TreeSet constructor to use the custom comparator)
Andreas_D
You should actually *use* the `Comparator` you defined in your sample code ;-)
Joachim Sauer
Also see `String.CASE_INSENSITIVE_ORDER` static Comparator on the String class
Jon Freedman
A: 

How about writing a Wrapper class to the List you are using, this would avoid to have inconsistent storage of the elements.

public class CaseInsensitiveStringList extends ArrayList<String> {

    @Override
    public void add(final int index, final String element) {
        super.add(index, element.toLowerCase());
    }

    @Override
    public boolean add(final String o) {
        return super.add(o.toLowerCase());
    }

    @Override
    public boolean addAll(final Collection<? extends String> c) {
        final ArrayList<String> temp = new ArrayList<String>(c.size());
        for (final String s : c) {
            temp.add(s.toLowerCase());
        }
        return super.addAll(temp);
    }

    @Override
    public boolean addAll(final int index, final Collection<? extends String> c) {
        final ArrayList<String> temp = new ArrayList<String>(c.size());
        for (final String s : c) {
            temp.add(s.toLowerCase());
        }
        return super.addAll(index, temp);
    }
}
Johannes Wachter