Georges Oates Larsen
Georges Oates Larsen

Reputation: 7102

Java get String CompareTo as a comparator object

I would like to sort and binary search a static array of strings via the String.CompareTo comparator.

The problem is that both sorting, and binary searching requires that a Comparator object be passed in -- So how do I pass in the built in string comparator?

Upvotes: 56

Views: 209604

Answers (13)

Aliciasiashia
Aliciasiashia

Reputation: 79

I find the most clean way is to use lambda expression.

Like this: strings.sort((a, b) -> a.compareTo(b));


If you want to know more—

In javascript or other functional languages, we can simply pass a function as an argument, that is, compareTo is itself a Comparator.

In java, functions are not first-class citizens. Therefore, you need to wrap it in a class that subclasses Comparator and define the method as the only method of that class.

Certainly it looks weird and verbose, b/c OOP is not designed to do something like this. Lambda expression does exactly that (subclassing, defining the method) behind the scene, although the expression itself looks the same as in functional language.

Upvotes: 2

João Pedro Schmitt
João Pedro Schmitt

Reputation: 1498

You can use the StringUtils.compare("a", "b")

Upvotes: -2

kosa
kosa

Reputation: 66657

You may write your own comparator

public class ExampleComparator  implements Comparator<String> {
  public int compare(String obj1, String obj2) {
    if (obj1 == obj2) {
        return 0;
    }
    if (obj1 == null) {
        return -1;
    }
    if (obj2 == null) {
        return 1;
    }
    return obj1.compareTo(obj2);
  }
}

Upvotes: 51

Code-Apprentice
Code-Apprentice

Reputation: 83557

The Arrays class has versions of sort() and binarySearch() which don't require a Comparator. For example, you can use the version of Arrays.sort() which just takes an array of objects. These methods call the compareTo() method of the objects in the array.

Upvotes: 22

Michael Brewer-Davis
Michael Brewer-Davis

Reputation: 14276

If you do find yourslef needing a Comparator, and you already use Guava, you can use Ordering.natural().

Upvotes: 14

brunesto
brunesto

Reputation: 440

Ok this is a few years later but with java 8 you can use Comparator.naturalOrder():

http://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html#naturalOrder--

From javadoc:

static <T extends Comparable<? super T>> Comparator<T> naturalOrder()

Returns a comparator that compares Comparable objects in natural order. The returned comparator is serializable and throws NullPointerException when comparing null.

Upvotes: 20

Sharcoux
Sharcoux

Reputation: 6105

To generalize the good answer of Mike Nakis with String.CASE_INSENSITIVE_ORDER, you can also use :

Collator.getInstance();

See Collator

Upvotes: 3

Mike Nakis
Mike Nakis

Reputation: 62045

This is a generic Comparator for any kind of Comparable object, not just String:

package util;

import java.util.Comparator;

/**
 * The Default Comparator for classes implementing Comparable.
 *
 * @param <E> the type of the comparable objects.
 *
 * @author Michael Belivanakis (michael.gr)
 */
public final class DefaultComparator<E extends Comparable<E>> implements Comparator<E>
{
    @SuppressWarnings( "rawtypes" )
    private static final DefaultComparator<?> INSTANCE = new DefaultComparator();

    /**
     * Get an instance of DefaultComparator for any type of Comparable.
     *
     * @param <T> the type of Comparable of interest.
     *
     * @return an instance of DefaultComparator for comparing instances of the requested type.
     */
    public static <T extends Comparable<T>> Comparator<T> getInstance()
    {
        @SuppressWarnings("unchecked")
        Comparator<T> result = (Comparator<T>)INSTANCE;
        return result;
    }

    private DefaultComparator()
    {
    }

    @Override
    public int compare( E o1, E o2 )
    {
        if( o1 == o2 )
            return 0;
        if( o1 == null )
            return 1;
        if( o2 == null )
            return -1;
        return o1.compareTo( o2 );
    }
}

How to use with String:

Comparator<String> stringComparator = DefaultComparator.getInstance();

Upvotes: 11

Rafał Jankowski
Rafał Jankowski

Reputation: 21

Regarding Nambari's answer there was a mistake. If you compare values using double equal sign == program will never reach compare method, unless someone will use new keyword to create String object which is not the best practice. This might be a bit better solution:

public int compare(String o1, String o2) {
        if (o1 == null && o2 == null){return 0;}
        if (o1 == null) { return -1;}
        if (o2 == null) { return 1;}
        return o1.compareTo(o2);
    }

P.S. Thanks for comments ;)

Upvotes: -1

Joseph Nields
Joseph Nields

Reputation: 5661

Again, don't need the comparator for Arrays.binarySearch(Object[] a, Object key) so long as the types of objects are comparable, but with lambda expressions this is now way easier.

Simply replace the comparator with the method reference: String::compareTo

E.g.:

Arrays.binarySearch(someStringArray, "The String to find.", String::compareTo);

You could also use

Arrays.binarySearch(someStringArray, "The String to find.", (a,b) -> a.compareTo(b));

but even before lambdas, there were always anonymous classes:

Arrays.binarySearch(
                someStringArray,
                "The String to find.",
                new Comparator<String>() {
                    @Override
                    public int compare(String o1, String o2) {
                        return o1.compareTo(o2);
                    }
                });

Upvotes: 10

Anthony
Anthony

Reputation: 12736

Solution for Java 8 based on java.util.Comparator.comparing(...):

Comparator<String> c = Comparator.comparing(String::toString);

or

Comparator<String> c = Comparator.comparing((String x) -> x);

Upvotes: 53

Sudhakar
Sudhakar

Reputation: 3180

We can use the String.CASE_INSENSITIVE_ORDER comparator to compare the strings in case insensitive order.

Arrays.binarySearch(someStringArray, "The String to find.",String.CASE_INSENSITIVE_ORDER);

Upvotes: 3

Mike Nakis
Mike Nakis

Reputation: 62045

Also, if you want case-insensitive comparison, in recent versions of Java the String class contains a public static final field called CASE_INSENSITIVE_ORDER which is of type Comparator<String>, as I just recently found out. So, you can get your job done using String.CASE_INSENSITIVE_ORDER.

Upvotes: 6

Related Questions