Как упростить нулевую безопасную реализацию compareTo ()?

У меня были те же проблемы, но после очистки моего проекта и запуска его снова он отлично работает.

140
задан Community 23 May 2017 в 11:54
поделиться

5 ответов

Можно извлечь метод:

public int cmp(String txt, String otherTxt)
{
    if ( txt == null )
        return otjerTxt == null ? 0 : 1;

    if ( otherTxt == null )
          return 1;

    return txt.compareToIgnoreCase(otherTxt);
}

public int compareTo(Metadata other) {
   int result = cmp( name, other.name); 
   if ( result != 0 )  return result;
   return cmp( value, other.value); 

}

4
ответ дан Yoni Roit 23 May 2017 в 21:54
поделиться

Я реализовал бы пустой безопасный компаратор. Там может быть реализация, но это столь просто для реализации, что я всегда прокручивал свое собственное.

Примечание: Ваш компаратор выше, если оба имена являются пустыми, даже не сравнит поля значения. Я не думаю, что это - то, что Вы хотите.

я реализовал бы это с чем-то как следующее:

// primarily by name, secondarily by value; null-safe; case-insensitive
public int compareTo(final Metadata other) {

    if (other == null) {
        throw new NullPointerException();
    }

    int result = nullSafeStringComparator(this.name, other.name);
    if (result != 0) {
        return result;
    }

    return nullSafeStringComparator(this.value, other.value);
}

public static int nullSafeStringComparator(final String one, final String two) {
    if (one == null ^ two == null) {
        return (one == null) ? -1 : 1;
    }

    if (one == null && two == null) {
        return 0;
    }

    return one.compareToIgnoreCase(two);
}

РЕДАКТИРОВАНИЕ: Фиксированные опечатки в примере кода. Это - то, что я получаю для того, чтобы не протестировать его сначала!

РЕДАКТИРОВАНИЕ: Продвинутый nullSafeStringComparator к помехам.

90
ответ дан Sentinel 23 May 2017 в 21:54
поделиться

Я всегда рекомендую использовать свободное городское население Apache, так как это, скорее всего, будет лучше, чем одно, можно записать самостоятельно. Плюс Вы может затем сделать 'реальную' работу скорее затем переосмысление.

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

В Вашем случае у Вас может быть статическая членская переменная, которая делает сравнение и затем Ваш compareTo метод просто ссылки это.

Somthing как

class Metadata implements Comparable<Metadata> {
private String name;
private String value;

static NullComparator nullAndCaseInsensitveComparator = new NullComparator(
        new Comparator<String>() {

            @Override
            public int compare(String o1, String o2) {
                // inputs can't be null
                return o1.compareToIgnoreCase(o2);
            }

        });

@Override
public int compareTo(Metadata other) {
    if (other == null) {
        return 1;
    }
    int res = nullAndCaseInsensitveComparator.compare(name, other.name);
    if (res != 0)
        return res;

    return nullAndCaseInsensitveComparator.compare(value, other.value);
}

}

, Даже если Вы решаете к самокрутке, помните об этом классе, так как это очень полезно при упорядочивании списков thatcontain пустые элементы.

13
ответ дан Patrick 23 May 2017 в 21:54
поделиться

Посмотрите нижнюю часть этого ответа для обновленного (2013) решение с помощью Гуавы.

<час>

Это - то, с чем я в конечном счете пошел. Оказалось, что у нас уже был служебный метод для пустого безопасного Сравнения строк, таким образом, простое решение состояло в том, чтобы использовать это. (Это - большая кодовая база; легкий пропустить такого рода вещь :)

public int compareTo(Metadata other) {
    int result = StringUtils.compare(this.getName(), other.getName(), true);
    if (result != 0) {
        return result;
    }
    return StringUtils.compare(this.getValue(), other.getValue(), true);
}

Это - то, как помощник определяется (она перегружается так, чтобы можно было также определить, аннулирует ли, на первом месте или длятся, если Вы хотите):

public static int compare(String s1, String s2, boolean ignoreCase) { ... }

, Таким образом, это - по существу то же как [1 114] ответ Eddie (хотя я не назвал бы статический вспомогательный метод компаратор ), и тот из uzhin также.

Так или иначе, в целом, я сильно одобрил бы решение Patrick, поскольку я думаю, что это - хорошая практика для пользований созданными библиотеками, когда это возможно. ( Знают и пользуются библиотеками , как говорит Josh Bloch.), Но в этом случае который не привел бы к самому чистому, самому простому коду.

Редактирование (2009): Apache версия

Наборов палаты общин На самом деле, вот способ сделать решение на основе Apache палатой общин NullComparator более простой. Объедините его с нечувствительный к регистру Comparator обеспеченный в String класс:

public static final Comparator<String> NULL_SAFE_COMPARATOR 
    = new NullComparator(String.CASE_INSENSITIVE_ORDER);

@Override
public int compareTo(Metadata other) {
    int result = NULL_SAFE_COMPARATOR.compare(this.name, other.name);
    if (result != 0) {
        return result;
    }
    return NULL_SAFE_COMPARATOR.compare(this.value, other.value);
}

Теперь это довольно изящно, я думаю. (Всего одна маленькая проблема остается: палата общин NullComparator не поддерживает дженериков, таким образом, существует присвоение непроверенное.)

Обновление (2013): версия

Гуавы Почти 5 лет спустя, вот то, как я занялся бы своим исходным вопросом. При кодировании в Java я (конечно), использовал бы Гуава . (И вполне конечно не Apache палата общин.)

Помещенный эта константа где-нибудь, например, в классе "StringUtils":

public static final Ordering<String> CASE_INSENSITIVE_NULL_SAFE_ORDER =
    Ordering.from(String.CASE_INSENSITIVE_ORDER).nullsLast(); // or nullsFirst()

Затем в public class Metadata implements Comparable<Metadata>:

@Override
public int compareTo(Metadata other) {
    int result = CASE_INSENSITIVE_NULL_SAFE_ORDER.compare(this.name, other.name);
    if (result != 0) {
        return result;
    }
    return CASE_INSENSITIVE_NULL_SAFE_ORDER.compare(this.value, other.value);
}    

, Конечно, это почти идентично Apache версия палаты общин (оба использования JDK CASE_INSENSITIVE_ORDER), использование [1 110] являющийся единственной Определенной для гуавы вещью. Эта версия предпочтительна просто, потому что Гуава предпочтительна, как зависимость, к Наборам палаты общин. (Как [1 121] все соглашаются .)

, Если Вы задавались вопросом приблизительно [1 122] Ordering , обратите внимание, что это реализует Comparator. Это довольно удобно специально для более сложных потребностей сортировки, позволяя Вам, например, объединить несколько Упорядочиваний в цепочку с помощью [1 113]. Читайте Упорядочивание, Объясненное для больше!

21
ответ дан Community 23 May 2017 в 21:54
поделиться

Вы могли разработать свой класс, чтобы быть неизменными (Эффективный Java 2-й Ed. имеет большой раздел по этому, Объект 15: Минимизируйте переменчивость), и удостоверьтесь на конструкцию, что никакой не аннулирует, возможны (и используйте шаблон несуществующего объекта в случае необходимости). Затем можно пропустить все те проверки и безопасно предположить, что значения не являются нулевыми.

3
ответ дан Fabian Steeg 23 May 2017 в 21:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: