Java TreeMap (comparator) и метод get игнорируют компаратор
public final Comparator<String> ID_IGN_CASE_COMP = new Comparator<String>() {
public int compare(String s1, String s2) {
return s1.compareToIgnoreCase(s2);
}
};
private Map< String, Animal > _animals = new TreeMap< String, Animal >(ID_IGN_CASE_COMP);
моя проблема в том, как использовать метод get(id), игнорируя данный компаратор. Я хочу, чтобы карта была нечувствительной к регистру, но я хочу, чтобы она была чувствительной к регистру, когда я получаю значения данным ключом.
7 ответов
Я думаю, что ответ прост. Реализуйте свой собственный компаратор, который делает сортировку без учета регистра, но делает не возврат 0 для "A"и " a"... сортируйте их тоже.
проблема в том, что ваш компаратор возвращает 0 для случая сравнения( "A", "a"), что означает, что это тот же ключ, что и для карты.
используйте компаратор, например:
public final Comparator<String> ID_IGN_CASE_COMP = new Comparator<String>() {
public int compare(String s1, String s2) {
int result = s1.compareToIgnoreCase(s2);
if( result == 0 )
result = s1.compareTo(s2);
return result;
}
};
тогда все ключи будут идти независимо от случая, и "a " и" A " все равно будут отсортированы вместе.
другими словами, get ("a") даст вам другое значение от get ("A")... и они оба появятся в итераторах keySet (). Они просто будут отсортированы вместе.
в TreeMap добавление двух ключей a и b (в этом порядке), так что compare(a, b) возвращает 0, приведет к тому, что последняя добавленная запись (b) перезапишет первую (a).
в вашем случае это означает, что никогда не будет никакого использования для нечувствительного к регистру get(id).
цитирование http://java.sun.com/javase/6/docs/api/java/util/TreeMap.html
обратите внимание, что порядок поддерживается отсортированной картой (будь то явная компаратор предоставляется) должен быть согласован с equals, если эта отсортированная карта должна правильно реализовать интерфейс карты. (См. Comparable или Comparator для точного определения согласованного с равными.) Это так, потому что интерфейс карты определяется в терминах операции equals, но карта выполняет все ключевые сравнения, используя свой метод compareTo (или compare), поэтому два ключа, которые считаются равными этим методом, с точки зрения отсортированной карты равны. Поведение отсортированной карты четко определенный, даже если его порядок несовместим с equals; он просто не подчиняется общему контракту интерфейса карты.
Это, наверное, не то, что вы хотите.
Если карта сравнительно мала, и вам не нужно извлекать отсортированные записи очень много раз, решение состоит в том, чтобы использовать HashMap (или TreeMap без явного задания компаратора) и сортировать записи без учета регистра, когда вам нужно их упорядочить.
для этого вам придется использовать две отдельные карты деревьев с одинаковым содержимым, но разными компараторами.
может быть, это сделает работу:
new Comparator<String>(){
public int compare(String s1, String s2)
{
String s1n = s1.toLowerCase();
String s2n = s2.toLowerCase();
if(s1n.equals(s2n))
{
return s1.compareTo(s2);
}
return s1n.compareTo(s2n);
}
};
}
вам понадобится multimap: каждая запись этого multimap сохраняет регистр ключи и aanother карта с оригинальными ключами в качестве значения.
есть много свободно используемых реализаций multimaps, таких как Общих Собраний, Google Коллекции, etc
в дополнение ко всем другим ответам и соглашаясь, что невозможно иметь одну структуру TreeMap с разными компараторами:
из вашего вопроса я понимаю, что у вас есть два требования: модель данных должна быть чувствительной к регистру (вы хотите, чтобы значения с учетом регистра при использовании get()
), ведущий должен быть нечувствительным к регистру (вы хотите, чтобы порядок с учетом регистра, презентация - это просто предположение).
предположим, мы заполняем карту сопоставления (АА,obj1), (АА,obj2), (АА,obj3), (АА,obj4). Итератор будет предоставлять значения в порядке: (obj4, obj3, obj2, obj1)(*). Теперь, какой порядок вы ожидаете, если карта была заказана без учета регистра? Все четыре ключа будут равны, а порядок не определен. Или вы ищете решение, которое разрешило бы коллекцию {obj1, obj2, obj3, obj4} для ключа "AA"? Но это другой подход.
поэтому призывает сообщество быть честным: поэтому мой совет в этом точка, чтобы посмотреть на ваше требование снова:)
(*) не проверено, предполагается, что 'A'
использовать floorEntry а то higherEntry в цикле, чтобы найти записи без учета регистра; остановитесь, когда найдете точное совпадение ключей.