5

以下のクラスの出力は次のとおりです。サイズは 3 サイズは 1

しかし、TreeSet を HashSet に変更すると、次のようになります。

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

になる

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

出力は次のとおりです。サイズは 3 サイズは 2

Set のサイズを変更しないで HashSet または TreeSet を使用して叫ぶ?重複を削除しているため、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()));
            }

        }

    }

編集:注:次を使用してハッシュセットをツリーセットに変換すると:

 Set<SuggestionDetailBean> sortedSet = new TreeSet<SuggestionDetailBean>(hashset);

重複の削除は、compareto メソッドではなくオブジェクトのハッシュコードと equals メソッドに基づいているため、正しい並べ替えが維持されます。

4

1 に答える 1

15

のJavadocにTreeSetよると:

インターフェースを正しく実装するためには、(明示的なコンパレーターが提供されているかどうかに関係なく) セットによって維持される順序付けがequals と一致している必要があることに注意してください。Set( equals と一致する正確な定義については、Comparable orを参照してください。) これは、インターフェイスが操作に関して定義されているためです。ただし、インスタンスはその(or ) メソッドを使用してすべての要素の比較を実行するため、2 つの要素はこれによって等しいと見なされます。方法は、セットの観点からは同等です。セットの動作は、 その順序付けが equals と一致しない場合でも明確に定義されています。の一般的な契約に従わないだけです。ComparatorSetequalsTreeSetcompareTocompareSetインターフェース。

したがって、問題はあなたの方法にあります。一貫性のない結果が得られるか、またはif および if のみcompareToというルールに従わない一貫した結果が得られます。a.compareTo(b) == 0a.equals(b)

たとえば、このビット:

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

は、「thisまたはotherがの場合、とが等しいdate == nullことを報告する」を意味しますが、これは確かにあなたが望むものではありません。thisother

于 2013-02-13T22:33:18.300 に答える