java HashSet 删除重复项但 TreeSet 不删除?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14864488/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
HashSet removes duplicates but TreeSet does not?
提问by blue-sky
Output of below class is : size is 3 size is 1
以下类的输出是:大小为 3 大小为 1
But if I change the TreeSet to a HashSet so line :
但是,如果我将 TreeSet 更改为 HashSet 所以行:
Set<SuggestionDetailBean> set = new TreeSet<SuggestionDetailBean>();
becomes
变成
Set<SuggestionDetailBean> set = new HashSet<SuggestionDetailBean>();
the output is : size is 3 size is 2
输出为:大小为 3 大小为 2
Shout using HashSet or TreeSet not change the size of Set ? Using HashSet seems to behave as expected because it is removing duplicates but when I use TreeSet the duplicates remain ? I think the hashcode and equals methods in SuggestionDetailBean are overriden correctly ?
大喊使用 HashSet 或 TreeSet 不会改变 Set 的大小?使用 HashSet 似乎表现得如预期,因为它正在删除重复项,但是当我使用 TreeSet 时,重复项仍然存在?我认为 SuggestionDetailBean 中的 hashcode 和 equals 方法被正确覆盖了?
Here is the code :
这是代码:
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()));
}
}
}
Edit : Note : if I convert the hashset to a treeset using :
编辑:注意:如果我使用以下方法将哈希集转换为树集:
Set<SuggestionDetailBean> sortedSet = new TreeSet<SuggestionDetailBean>(hashset);
Then correct sorting is maintained, as the removal of duplicates is based on the object hashcode and equals methods not the compareto method.
然后保持正确的排序,因为重复项的删除是基于对象哈希码和等于方法而不是 compareto 方法。
回答by ruakh
According to the Javadoc for TreeSet
:
Note that the ordering maintained by a set (whether or not an explicit comparator is provided) must be consistent with equalsif it is to correctly implement the
Set
interface. (SeeComparable
orComparator
for a precise definition of consistent with equals.) This is so because theSet
interface is defined in terms of theequals
operation, but aTreeSet
instance performs all element comparisons using itscompareTo
(orcompare
) method, so two elements that are deemed equal by this method are, from the standpoint of the set, equal. The behavior of a set iswell-defined even if its ordering is inconsistent with equals; it just fails to obey the general contract of theSet
interface.
请注意,如果要正确实现接口,则集合维护的排序(无论是否提供显式比较器)必须与 equals 一致
Set
。(请参阅Comparable
或Comparator
以获取与 equals 一致的精确定义。)之所以如此,是因为Set
接口是根据equals
操作定义的,但TreeSet
实例使用其compareTo
(orcompare
) 方法执行所有元素比较,因此被 this 视为相等的两个元素从集合的角度来看,方法是相等的。集合的行为 是明确定义的,即使它的顺序与 equals 不一致;它只是不遵守一般合同Set
界面。
So, the problem is with your compareTo
method: either it's giving inconsistent results, or else it's giving consistent results that don't obey the rule that a.compareTo(b) == 0
if and only if a.equals(b)
.
所以,问题出在你的compareTo
方法上:要么给出不一致的结果,要么给出不遵守规则的一致结果,a.compareTo(b) == 0
当且仅当a.equals(b)
.
For example, this bit:
例如,这一点:
if(this.date == null || other.date == null){
return 0;
}
means "if either this
or other
has date == null
, then report that this
and other
are equal", which is certainly not what you want.
意思是“如果有this
或者other
有date == null
,那么报告那个this
和other
是相等的”,这当然不是你想要的。