0

Java: Получение String CompareTo в качестве объекта Comparator

17

Я хотел бы отсортировать и выполнить бинарный поиск по статическому массиву строк, используя компаратор String.CompareTo.

Проблема заключается в том, что как для сортировки, так и для бинарного поиска требуется передать объект компаратора. Как мне передать встроенный компаратор для строк?

5 ответ(ов)

0

Вы можете написать свой собственный компаратор следующим образом:

import java.util.Comparator;

public class ExampleComparator implements Comparator<String> {
    @Override
    public int compare(String obj1, String obj2) {
        // Проверка на равенство ссылок
        if (obj1 == obj2) {
            return 0;
        }
        // Проверка на null
        if (obj1 == null) {
            return -1;
        }
        if (obj2 == null) {
            return 1;
        }
        // Сравнение строк
        return obj1.compareTo(obj2);
    }
}

Этот компаратор реализует интерфейс Comparator<String>, который позволяет вам определять порядок сортировки строк. В данном примере сначала проверяется, ссылаются ли обе строки на один и тот же объект. Если да, возвращается 0, что означает, что строки равны. Далее идет проверка на null, где null считается меньшим, чем любое другое значение. В конце используется метод compareTo() для стандартного сравнения строк.

Используя этот компаратор, вы можете сортировать коллекции строк по вашему критерию.

0

Несколько лет спустя, но с Java 8 вы можете использовать Comparator.naturalOrder():

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

Согласно документации:

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

Этот метод возвращает компаратор, который сравнивает объекты Comparable в их естественном порядке. Возвращаемый компаратор является сериализуемым и выбрасывает NullPointerException при сравнении значений null.

0

Это универсальный Comparator для любых объектов, реализующих интерфейс Comparable, а не только для строк:

package util;

import java.util.Comparator;

/**
 * Стандартный компаратор для классов, реализующих Comparable.
 *
 * @param <E> тип сравниваемых объектов.
 *
 * @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();

    /**
     * Получить экземпляр DefaultComparator для любого типа Comparable.
     *
     * @param <T> тип интересующего Comparable.
     *
     * @return экземпляр DefaultComparator для сравнения экземпляров запрашиваемого типа.
     */
    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);
    }
}

Как использовать с String:

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

Этот компаратор будет корректно сравнивать объекты String, а также любые другие объекты, реализующие интерфейс Comparable, что делает его универсальным решением для различных типов данных.

0

Вам не нужен компаратор для метода Arrays.binarySearch(Object[] a, Object key), если объекты в массиве сравнимы между собой. Однако с введением лямбда-выражений это стало намного проще.

Просто замените компаратор на метод-ссылку: String::compareTo

Например:

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

Вы также можете использовать

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

Но даже до появления лямбда-выражений всегда были анонимные классы:

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

Таким образом, с помощью лямбда-выражений или метод-ссылок можно сделать код короче и более читаемым.

0

Если вам нужна нечувствительная к регистру сортировка строк, в последних версиях Java класс String содержит публичное статическое финальное поле CASE_INSENSITIVE_ORDER, которое представляет собой объект типа Comparator<String>. Я узнал об этом совсем недавно. Таким образом, вы можете использовать String.CASE_INSENSITIVE_ORDER, чтобы выполнить вашу задачу.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь