He escrito un código para encontrar imágenes únicas. Dos imágenes son iguales si tienen el mismo nombre (aunque la extensión sea diferente) y el tamaño es igual (ancho * largo). Pero está fallando en encontrar imágenes únicas. Incluso después de anular el método equals, el método HashSet no puede identificar dos objetos similares.
import java.util.*; class UniqueImages { public static class Image { private String filename; private int width; private int height; public Image(String filename, int width, int height) { this.filename = filename; this.width = width; this.height = height; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((filename == null) ? 0 : filename.hashCode()); result = prime * result + height; result = prime * result + width; return result; } /** * Two Images are considered equal if they have * the same filename (without the extension), and the * same number of pixels. * Thus, flag.jpg with width=60 height=40 is * equal to flag.gif with width=40 and height=60 */ public boolean equals(Object other) { Image o = (Image)other; if (filename == null || o.filename == null) return false; String[] components = filename.split("\\."); String[] ocomponents = o.filename.split("\\."); return components[0].equals(ocomponents[0]) && width * height == o.width * o.height; } public String toString() { return "Image: filename=" + filename + " Size=" + width*height; } } public static void printImages(Set<Image> images) { for(Image image: images) { System.out.println(image); } } public static void main(String[] args) { Image[] images = {new Image("flag.jpg", 40, 60), new Image("flag.gif", 40, 60), new Image("smile.gif", 100, 200), new Image("smile.gif", 50, 400), new Image("other.jpg", 40, 60), new Image("lenna.jpg", 512, 512), new Image("Lenna.jpg", 512, 512)}; Set<Image> set = new HashSet<Image>(Arrays.asList(images)); UniqueImages.printImages(set); } }Si el método equals() considera que dos imágenes que tienen el mismo tamaño total son iguales (incluso si no tienen el mismo width y height ), también deberían tener el mismo hashCode() .
Pero ese no es el único problema. También debe cambiar hashCode() para ignorar los sufijos de nombre de archivo, para que se ajuste a la implementación de equals() .
public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((filename == null) ? 0 : filename.split("\\.")[0].hashCode()); result = prime * result + (height * width); return result; } Con estos dos cambios, HashSet eliminará dos duplicados, lo que dará como resultado:
Image: filename=smile.gif Size=20000 Image: filename=flag.jpg Size=2400 Image: filename=lenna.jpg Size=262144 Image: filename=other.jpg Size=2400 Image: filename=Lenna.jpg Size=262144Eran ya dio la respuesta. Sin embargo, me gustaría resaltar los problemas en su implementación de .equals() . Su yeso no es seguro. Así es como lo escribiría (usando la plantilla proporcionada en Java efectivo de Bloch):
public boolean equals(Object o) { if(o == this) { return true; } if(!(o instance of Image)) { return false; } Image o = (Image)other; if (filename == null || o.filename == null) return false; String[] components = filename.split("\\."); String[] ocomponents = o.filename.split("\\."); return components[0].equals(ocomponents[0]) && width * height == o.width * o.height; }