Java: Получение String CompareTo в качестве объекта Comparator
Я хотел бы отсортировать и выполнить бинарный поиск по статическому массиву строк, используя компаратор String.CompareTo.
Проблема заключается в том, что как для сортировки, так и для бинарного поиска требуется передать объект компаратора. Как мне передать встроенный компаратор для строк?
5 ответ(ов)
Вы можете написать свой собственный компаратор следующим образом:
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()
для стандартного сравнения строк.
Используя этот компаратор, вы можете сортировать коллекции строк по вашему критерию.
Несколько лет спустя, но с 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
.
Это универсальный 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
, что делает его универсальным решением для различных типов данных.
Вам не нужен компаратор для метода 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);
}
});
Таким образом, с помощью лямбда-выражений или метод-ссылок можно сделать код короче и более читаемым.
Если вам нужна нечувствительная к регистру сортировка строк, в последних версиях Java класс String
содержит публичное статическое финальное поле CASE_INSENSITIVE_ORDER
, которое представляет собой объект типа Comparator<String>
. Я узнал об этом совсем недавно. Таким образом, вы можете использовать String.CASE_INSENSITIVE_ORDER
, чтобы выполнить вашу задачу.
Преобразование объекта JS в строку JSON
Сортировка ArrayList пользовательских объектов по свойству
Преобразование 'ArrayList<String>' в 'String[]' в Java
Как сгенерировать случайную алфавитно-цифровую строку
Как преобразовать строку Java в byte[]?