以下课程的输出是: 大小是3 大小是1
但是,如果我将TreeSet更改为HashSet,那么行:
Set<SuggestionDetailBean> set = new TreeSet<SuggestionDetailBean>();
变为
Set<SuggestionDetailBean> set = new HashSet<SuggestionDetailBean>();
输出是: 大小是3 大小是2
使用HashSet或TreeSet喊出不改变Set的大小? 使用HashSet似乎表现得像预期的那样,因为它正在删除重复项,但是当我使用TreeSet时,重复项仍然存在? 我认为SuggestionDetailBean中的hashcode和equals方法是否被正确覆盖?
以下是代码:
public class TestSet {
public static void main(String args[]){
SuggestionDetailBean s = new SuggestionDetailBean();
s.setTagList("teddst");
s.setUrl("testurl");
SuggestionDetailBean s2 = new SuggestionDetailBean();
s2.setTagList("teddst");
s2.setUrl("testurl");
SuggestionDetailBean s3 = new SuggestionDetailBean();
s3.setTagList("tessdafat");
s3.setUrl("fdfaasdfredtestur ldd");
List<SuggestionDetailBean> list = new ArrayList<SuggestionDetailBean>();
list.add(s);
list.add(s2);
list.add(s3);
Set<SuggestionDetailBean> set = new TreeSet<SuggestionDetailBean>();
set.addAll(list);
System.out.println("size is "+list.size());
System.out.println("size is "+set.size());
}
}
public class SuggestionDetailBean implements Comparable<Object> {
private String url;
private String tagList;
private String numberOfRecommendations;
private String date;
private String time;
private String summary;
private String truncatedUrl;
public void setTruncatedUrl(String truncatedUrl) {
if(truncatedUrl.length() > 20){
truncatedUrl = truncatedUrl.substring(0, 20)+"...";
}
this.truncatedUrl = truncatedUrl;
}
public String getSummary() {
if(summary == null){
return "";
}
else {
return summary;
}
}
public void setSummary(String summary) {
this.summary = summary;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getTime() {
return time;
}
public String getTruncatedUrl() {
return this.truncatedUrl;
}
public void setTime(String time) {
this.time = time;
}
public String getTagList() {
if(tagList == null){
return "";
}
else {
return tagList;
}
}
public void setTagList(String tagList) {
this.tagList = tagList;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getNumberOfRecommendations() {
return numberOfRecommendations;
}
public void setNumberOfRecommendations(String numberOfRecommendations) {
this.numberOfRecommendations = numberOfRecommendations;
}
@Override
public int compareTo(Object o) {
DateFormat formatter;
Date date1 = null;
Date date2 = null;
SuggestionDetailBean other = (SuggestionDetailBean) o;
if(this.date == null || other.date == null){
return 0;
}
formatter = new SimpleDateFormat(SimpleDateFormatEnum.DATE.getSdfType()+" "+SimpleDateFormatEnum.TIME.getSdfType());
try {
date1 = (Date) formatter.parse(this.date + " " + this.time);
date2 = (Date) formatter.parse(other.date + " " + other.time);
} catch (ParseException e) {
System.out.println("Exception thrown in"+this.getClass().getName()+", compareTo method");
e.printStackTrace();
}
catch(NullPointerException npe){
System.out.println("Exception thrown "+npe.getMessage()+" date1 is "+date1+" date2 is "+date2);
}
return date2.compareTo(date1);
}
@Override
public int hashCode() {
return this.url.hashCode();
}
@Override
public boolean equals(Object obj) {
SuggestionDetailBean suggestionDetailBean = (SuggestionDetailBean) obj;
if(StringUtils.isEmpty(this.getTagList())){
return this.getUrl().equals(suggestionDetailBean.getUrl());
}
else {
return (this.getTagList().equals(suggestionDetailBean.getTagList())) &&
(this.getUrl().equals(suggestionDetailBean.getUrl()));
}
}
}
编辑: 注意:如果我使用以下方法将hashset转换为树集:
Set<SuggestionDetailBean> sortedSet = new TreeSet<SuggestionDetailBean>(hashset);
然后保持正确的排序,因为删除重复项基于对象哈希码和equals方法而不是compareto方法。
答案 0 :(得分:15)
注意由一组维护的排序(无论是否显式 提供比较器)如果是,则必须
与equals 一致 正确实现 Set
接口。 (见Comparable
或Comparator
以获得与一致的精确定义 等于。)这是因为Set
接口定义在equals
操作的术语,但是TreeSet
实例 使用compareTo
执行所有元素比较(或compare
)方法,因此这个方法认为两个元素相等 从集合的角度来看,是平等的。一组的行为 即使它的排序与equals不一致,也是明确定义的;它 只是没有遵守Set
接口的一般合同。
所以,问题出在你的compareTo
方法上:要么是提供不一致的结果,要么就是提供一致的结果,这些结果不符合a.compareTo(b) == 0
的规则,当且仅当{{1} }。
例如,这一位:
a.equals(b)
表示“如果 if(this.date == null || other.date == null){
return 0;
}
或this
有other
,则报告date == null
和this
相等”,这肯定不是您想要的