5

Output of below class is : size is 3 size is 1

But if I change the TreeSet to a HashSet so line :

Set<SuggestionDetailBean> set = new TreeSet<SuggestionDetailBean>();

becomes

Set<SuggestionDetailBean> set = new HashSet<SuggestionDetailBean>();

the output is : size is 3 size is 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 ?

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.

4

1 回答 1

15

根据JavadocTreeSet

请注意,如果要正确实现接口,集合维护的顺序(无论是否提供显式比较器)必须与 equals 一致。Set(有关与 equals 一致的精确定义,请参见Comparable or 。)这是因为接口是根据操作定义的,但实例使用其(or ) 方法执行所有元素比较,因此两个元素被视为相等从集合的角度来看,方法是相等的。一个集合的行为 明确定义的,即使它的顺序与equals不一致;它只是不遵守总合同ComparatorSetequalsTreeSetcompareTocompareSet界面。

所以,问题出在你的compareTo方法上:要么给出不一致的结果,要么给出一致的结果,不遵守a.compareTo(b) == 0if 且仅当a.equals(b).

例如,这个位:

            if(this.date == null || other.date == null){
                return 0;
            }   

意思是“如果有thisotherdate == null,则报告thisother相等”,这当然不是你想要的。

于 2013-02-13T22:33:18.300 回答