Я написал код для поиска уникальных изображений. Два изображения равны, если у них одинаковое имя (даже если расширение разное) и одинаковый размер (ширина * длина). Но не удается найти уникальные изображения. Даже после переопределения метода equals метод HashSet не может идентифицировать два похожих объекта.
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);
}
}
2 ответа
Если ваш метод equals()
считает два изображения с одинаковым общим размером равными (даже если у них разные width
и height
), они также должны иметь одинаковые hashCode()
.
Но это не единственная проблема. Вам также следует изменить hashCode()
, чтобы игнорировать суффиксы имени файла, чтобы он соответствовал реализации 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;
}
С этими двумя изменениями HashSet
удалит два дубликата, что приведет к:
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=262144
Эран уже дал ответ. Однако я хотел бы выделить проблемы в вашей реализации .equals()
. Ваш гипс небезопасен. Вот как я бы это написал (используя шаблон, приведенный в Effective Java Блоха):
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;
}
Похожие вопросы
Новые вопросы
java
Java - это язык программирования высокого уровня. Используйте этот тег, если у вас возникли проблемы с использованием или пониманием самого языка. Этот тег редко используется отдельно и чаще всего используется вместе с [spring], [spring-boot], [jakarta-ee], [android], [javafx], [hadoop], [gradle] и [maven].