Java: SortedMap, TreeMap, comparáveis? Como usar?
-
10-07-2019 - |
Pergunta
Eu tenho uma lista de objetos que eu preciso para classificar de acordo com propriedades de um dos seus campos. Ouvi dizer que SortedMap e comparadores são a melhor maneira de fazer isso.
- Do I implementar comparável com a classe Eu estou classificação, ou eu criar uma nova classe?
- Como faço para instanciar o SortedMap e passar o comparador?
- Como funciona a classificação? Será que vai classificar automaticamente tudo como são inseridos novos objetos?
EDIT: Este código está me dando um erro:
private TreeMap<Ktr> collection = new TreeMap<Ktr>();
(Ktr implementos Comparator<Ktr>
). Eclipse diz que está esperando algo como TreeMap<K, V>
, por isso o número de parâmetros que eu estou fornecendo está incorreto.
Solução
- A forma mais simples é implementar
Comparable
com seus objetos existentes, embora você poderia, em vez criar umComparator
e passá-lo para oSortedMap
.
Note-se queComparable
eComparator
são duas coisas diferentes; umComparable
implementação de classe comparathis
para outro objeto, enquanto umaComparator
implementação de classe compara dois outros objetos. - Se você implementar
Comparable
, você não precisa passar nada de especial para o construtor. Apenasnew TreeMap<MyObject>()
chamada. ( Editar:.! , exceto que, naturalmente, precisaMaps
dois parâmetros genéricos, não um Tolo me)
Se você em vez disso criar outra classe que implementaComparator
, passar uma instância dessa classe para o construtor. - Sim, de acordo com a
TreeMap
Javadocs .
Editar: Na re-ler a pergunta, nada disso faz sentido. Se você já tem uma lista, a coisa sensata a fazer é implementar Comparable
e depois chamar Collections.sort
nele. Não mapas são necessários.
Um código pouco:
public class MyObject implements Comparable<MyObject> {
// ... your existing code here ...
@Override
public int compareTo(MyObject other) {
// do smart things here
}
}
// Elsewhere:
List<MyObject> list = ...;
Collections.sort(list);
Tal como acontece com o SortedMap
, você poderia, em vez criar um Comparator<MyObject>
e passá-lo para Collections.sort(List, Comparator)
.
Outras dicas
1.
Isso depende da situação. Digamos que o objeto A deve resolver antes que o objeto B no seu conjunto. Se ele geralmente faz sentido considerar A menos de B, em seguida, implementar Comparável faria sentido. Se a ordem só faz sentido no contexto em que você usa o conjunto, então você provavelmente deve criar um comparador.
2.
new TreeMap(new MyComparator());
Ou sem criar uma classe MyComparator:
new TreeMap(new Comparator<MyClass>() {
int compare(MyClass o1, MyClass o2) { ... }
});
3. Sim.
Uma vez que você tem uma lista e obter um erro porque você tem um argumento no mapa eu suponho que você quer um conjunto classificado:
SortedSet<Ktr> set = new TreeSet<Ktr>(comparator);
Isto irá manter o conjunto classificado, isto é, uma iteração irá retornar os elementos em sua ordem de classificação. Existem também métodos específicos para SortedSet que você pode querer usar. Se você também quiser ir para trás você pode usar NavigableSet .
A minha resposta assume que você está usando a implementação TreeMap
de SortedMap
.
1). Se usando TreeMap
, você tem uma escolha. Você pode implementar Comparable
diretamente na sua classe ou passar um Comparator
separado para o construtor.
2) Exemplo:.
Comparator<A> cmp = new MyComparator();
Map<A,B> map = new TreeMap<A,B>(myComparator);
3.) Sim, isso é correto. Internamente TreeMap usa uma árvore rubro-negro para armazenar elementos, a fim de que eles são inseridos; o custo do tempo de execução de um inserto (ou recuperação) é O (log N).
Você faz um Comparator<ClassYouWantToSort>
. Em seguida, o comparador compara o campo que você deseja classificar.
Quando você cria o TreeMap
, você cria um TreeMap<ClassYouWantToSort>
, e você passar no Comparator
como um argumento. Então, como você inserir objetos do tipo ClassYouWantToSort
, o TreeMap
usa seu Comparator
para classificá-los corretamente.
EDIT: Notas Como Adamski, você também pode fazer ClassYouWantToSort
si Comparable
. A vantagem é que você tem menos classes para lidar com, o código é mais simples, e ClassYouWantToSort
recebe uma ordenação padrão conveniente. A desvantagem é que ClassYouWantToSort
pode não ter um único ordenamento óbvio, e por isso você vai ter que implementar Comparables
para outras situações de qualquer maneira. Você também pode não ser capaz de mudar ClassYouWantToSort
.
EDIT2: Se você só tem um monte de objetos que você está jogando para a coleção, e não é um Map
(ou seja, não é um mapeamento a partir de um conjunto de objetos para outro), então você quer um TreeSet
, não um TreeMap
.