Pregunta

Me gustaría tener un SortedSet de Colecciones (Establece sí mismos, en este caso, pero no necesariamente en general), que ordena por tamaño de la colección. Esto parece violar la proscripción tener Comparador ser coherente con equals () -. Es decir, dos colecciones pueden ser desiguales (por tener diferentes elementos), pero comparar con el mismo valor (porque tienen el mismo número de elementos)

Teóricamente, yo también podría poner en los medios comparador para ordenar conjuntos de igual tamaño, pero el uso de la clase no tomar ventaja de eso, y no hay realmente una manera útil + intuitiva para comparar las colecciones de igual tamaño (al menos, en mi caso particular), por lo que parece un desperdicio.

¿Tiene este caso de inconsistencia parecer un problema?

¿Fue útil?

Solución

Como escribió ChssPly76 en un comentario, puede utilizar código hash para decidir la llamada compareTo en el caso en que dos colecciones tienen el mismo tamaño, pero no son iguales. Esto funciona bien, excepto en el caso improbable de que usted tiene dos colecciones con el mismo tamaño, no son iguales, pero tienen el mismo código hash. Es cierto que las posibilidades de que eso ocurra son bastante pequeñas, pero es concebible. Si usted quiere ser muy cuidadoso, en lugar de hashCode, utilice System.identityHashCode lugar. Esto debe darle un número único para cada colección, y no debe recibir colisiones.

Al final del día, esto le da la funcionalidad de tener las Colecciones en el conjunto clasificado por tamaño, con orden arbitrario en el caso de las dos colecciones con juego del tamaño. Si esto es todo lo que necesita, no es mucho más lenta que la comparación habitual sería. Si necesita el ordenamiento ser consistente entre las diferentes instancias JVM, esto no funcionará y tendrá que hacerlo de otra manera.

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;
}

Otros consejos

SortedSet interfaz se extiende Set y por lo tanto deben ajustarse con el contrato se indica en la especificación Set.

El único camino posible para lograr que es tener un comportamiento equal() método de su elemento de ser coherente con su Comparator -. La razón de ello es que Set núcleo funciona en base a la igualdad, mientras que SortedSet opera basado en la comparación

Por ejemplo, método add() definido en la interfaz conjunto básico especifica que no se puede añadir un elemento al conjunto si ya existe un elemento cuyo método equal() volvería realidad con este nuevo elemento como argumento. Bueno, SortedSet no utiliza equal(), utiliza compareTo(). Así que si sus declaraciones de compareTo() false el elemento se añadirá incluso si eran equals() para volver true, rompiendo así el contrato Set.

Nada de esto es un práctica problema per se, sin embargo. SortedSet comportamiento siempre es coherente, incluso si compare() vs equals() no lo son.

  

Esto parece violar la proscripción   tener Comparador ser coherente   con equals () - es decir, dos colecciones   pueden ser desiguales (por tener diferentes   elementos), pero en comparación con el mismo   valor (porque tienen la misma   número de elementos).

No hay ningún requisito, ya sea declarado (en el Javadoc) o implícita, de que un Comparator sea consistente con la implementación de un objeto de boolean equals(Object).

Tenga en cuenta que Comparable y Comparator son interfaces de distintos con diferentes propósitos. Comparable se utiliza para definir un orden 'natural' para una clase. En ese contexto, sería una mala idea para equals y compateTo ser incompatibles. Por el contrario, un Comparator se utiliza cuando se desea utilizar un orden diferente al orden natural de una clase.

EDIT:. Aquí está el párrafo completo del Javadoc para SortedSet

  

Tenga en cuenta que el orden mantenido por una   conjunto ordenado (sea o no una explícita   comparador está provisto) debe estar   consistente con los iguales si el ordenado   conjunto es implementar correctamente el Conjunto   interfaz. (Véase la Comparable   interfaz o interfaz comparador para   una definición precisa de coherente   con los iguales.) Esto es así debido a que la   set interface se define en términos de   la operación es igual, pero una ordenados   conjunto realiza todas las comparaciones de elementos   utilizando su compareTo (o comparar)   método, por lo que dos elementos que son   atribuido igual por este método son, desde   el punto de vista del conjunto ordenado,   igual. El comportamiento de un conjunto ordenado es   bien definida, incluso si su pedido es   incompatible con iguales; es solo   no obedece el contrato general de   Configurar la interfaz.

He puesto de relieve la última frase. El punto es que una SortedSet tales funcionará como lo más probable es esperar, pero el comportamiento de algunas operaciones no coincidir exactamente con la especificación Set ... porque la especificación define su comportamiento en términos del método equals.

Así que, de hecho, hay es un requisito establecido para la consistencia (mi error), pero las consecuencias de ignorar que no son tan malas como se podría pensar. Por supuesto, le corresponde decidir si debe hacer eso. En mi opinión, debería estar bien, siempre y cuando usted comenta el código a fondo y asegúrese de que el SortedSet no 'fugas'.

Sin embargo, no es claro para mí que un comparador para colecciones que sólo se basa en un "tamaño" colecciones va a funcionar ... desde un punto de vista semántico. Es decir, lo que realmente quiere decir que todas las colecciones con (por ejemplo) 2 elementos son iguales? Esto significa que el conjunto de tan sólo puede contener una colección de cualquier tamaño dado ...

No hay razón para que un Comparator debe devolver los mismos resultados que equals(). De hecho, se introdujo la API Comparator porque equals() sólo no es suficiente: Si desea ordenar una colección, debe saber si dos elementos son en mayor o menor

.

Es un poco extraño que SortedSet como parte de la API estándar rompe el contrato se define en la interfaz Set y utiliza Comparador de definir la igualdad en lugar del método de igual a igual, pero eso es lo que es.

Si su problema real es para ordenar una colección de colecciones según el tamaño de las colecciones containted, usted es mejor de una lista, que se puede ordenar el uso de Collections.sort (Lista, Comparador>);

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top