Pergunta

Eu gostaria de ter um SortedSet de Coleções (Sets-se, neste caso, mas não necessariamente em geral), que classifica por tamanho Collection. Este parece violar a proibição de ter o Comparador ser consistente com equals () - ou seja, duas coleções podem ser desiguais (por ter elementos diferentes), mas comparar com o mesmo valor (porque eles têm o mesmo número de elementos)

Teoricamente, eu poderia também colocar nas formas comparador para conjuntos de classificação de tamanhos iguais, mas o uso desse tipo não iria tirar proveito disso, e não há realmente uma maneira útil + intuitiva para comparar as coleções de igual tamanho (pelo menos, no meu caso particular), de modo que parece um desperdício.

Será que este caso de inconsistência parecer um problema?

Foi útil?

Solução

escreveu Como ChssPly76 em um comentário, você pode usar hashCode para decidir a chamada compareTo no caso em que duas coleções têm o mesmo tamanho, mas não são iguais. Esta multa funciona, exceto no caso raro em que você tem duas coleções com o mesmo tamanho, não são iguais, mas têm o mesmo hashCode. Na verdade, as chances de isso acontecer são muito pequenas, mas é concebível. Se você quiser ter muito cuidado, em vez de hashCode, uso System.identityHashCode vez. Isso deve lhe dar um número único para cada coleção, e você não deve ter colisões.

No final do dia, isso lhe dá a funcionalidade de ter as coleções no Set classificadas por tamanho, com ordenação arbitrária no caso de duas coleções com tamanho correspondente. Se isso é tudo que você precisa, não é muito mais lento do que a comparação usual seria. Se você precisar a ordenação para ser consistente entre diferentes instâncias de JVM, isso não vai funcionar e você terá que fazê-lo de outra forma.

pseudocódigo:

if (a.equals(b)) {
    return 0;
} else if (a.size() > b.size()) {
    return 1;
} else if (b.size() > a.size()) {
    return -1;
} else {
    return System.identityHashCode(a) > System.identityHashCode(b) ? 1 : -1;
}

Outras dicas

SortedSet de interface estende núcleo Set e, portanto, deve estar em conformidade ao contrato descrito na especificação Set.

A única maneira possível de conseguir isso é ter método equal() comportamento do seu elemento de ser consistente com sua Comparator - a razão para isso é que Set núcleo opera com base na igualdade enquanto SortedSet opera com base na comparação

.

Por exemplo, add() método definido no especifica interface do conjunto do núcleo que você não pode adicionar um elemento para o conjunto se já existe um elemento cujo método equal() retornaria verdadeiro com este novo elemento como argumento. Bem, SortedSet não usa equal(), ele usa compareTo(). Portanto, se seus compareTo() retornos false seu elemento será adicionado mesmo que equals() foram para retornar true, quebrando assim o contrato Set.

Nada disto é um prática problema per se, no entanto. comportamento SortedSet é sempre consistente, mesmo se compare() vs equals() não são.

Este parece violar a proscrição para ter o Comparador ser consistente com equals () - ou seja, duas coleções pode ser desigual (por ter diferentes elementos), mas comparar com a mesma valor (porque eles têm o mesmo número de elementos).

Não há nenhuma exigência, seja declarado (no Javadoc) ou implícita, de que um Comparator ser consistente com a implementação de um objeto de boolean equals(Object).

Note que Comparable e Comparator são as interfaces distintas com diferentes propósitos. Comparable é utilizado para definir uma ordem de 'natural' de uma classe. Nesse contexto, seria uma má idéia para equals e compateTo ser inconsistente. Em contraste, um Comparator é usado quando você quiser usar uma ordem diferente da ordem natural de uma classe.

EDIT:. Aqui está o parágrafo completo do Javadoc para SortedSet

Note que a ordem mantida por um conjunto classificado (se ou não um explícita comparador é fornecido) deve ser consistente com iguais se o ordenado conjunto é implementar corretamente a Set interface. (Veja o Comparável interface de interface ou Comparador para uma definição precisa de consistente com iguais.) Isto é assim porque o interface do conjunto é definido em termos de a operação é igual, mas um classificado Conjunto executa todas as comparações elemento utilizando a sua compareTo (ou de comparação) Método, de modo que dois elementos de que são igualados por este método são, a partir de do ponto de vista do conjunto classificado, igual. O comportamento de um conjunto ordenado é bem definida mesmo que a sua encomenda é inconsistente com iguais; é só falhar em obedecer o contrato geral a interface Set.

Eu destaquei a sentença final. O ponto é que tal SortedSet vai funcionar como você provavelmente esperar, mas o comportamento de algumas operações não vai corresponder exatamente a especificação Set ... porque a especificação define o seu comportamento em termos de método equals.

Então, na verdade, há é uma exigência fixada para a consistência (o meu erro), mas as consequências de ignorar não são tão ruins como se poderia pensar. Claro, cabe decidir se você deve fazer isso. Em minha opinião, deve ser OK, desde que você comentar o código cuidadosamente e certifique-se de que o SortedSet não 'vazamento'.

No entanto, não está claro para mim que um comparador para coleções que só olha para um coleções "tamanho" está indo para o trabalho ... do ponto de vista semântico. Quero dizer, você realmente quer dizer que todas as coleções com (digamos) 2 elementos são iguais? Isto significa que o seu conjunto pode sempre apenas conter um conjunto de qualquer tamanho dado ...

Não há nenhuma razão para que um Comparator deve retornar os mesmos resultados que equals(). Na verdade, a API Comparator foi introduzido porque equals() apenas não é suficiente: Se você quiser classificar uma coleção, você deve saber se dois elementos são maior ou menor

.

É um pouco estranho que SortedSet como parte das quebras API padrão do contrato definidos na interface Set e usa o comparador para definir a igualdade em vez do método é igual, mas é assim que é.

Se o seu problema real é para classificar uma coleção de coleções de acordo com o tamanho das containted coleções, você é melhor de uma lista, que você pode classificar usando Collections.sort (List, Comparator>);

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top