Equals 方法不适用于两个相同的对象
Equals method is not working for two same object
我写了一个代码来查找独特的图片。如果两个图像具有相同的名称(即使扩展名不同)并且大小相等(宽度 * 长度),则它们是相等的。
但它无法找到独特的图像。
即使在覆盖 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);
}
}
如果您的 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
Eran已经给出了答案。但是,我想强调一下 .equals()
实施中的问题。你的演员阵容不安全。我会这样写(使用 Bloch 的 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;
}
我写了一个代码来查找独特的图片。如果两个图像具有相同的名称(即使扩展名不同)并且大小相等(宽度 * 长度),则它们是相等的。 但它无法找到独特的图像。 即使在覆盖 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);
}
}
如果您的 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
Eran已经给出了答案。但是,我想强调一下 .equals()
实施中的问题。你的演员阵容不安全。我会这样写(使用 Bloch 的 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;
}