Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HashSet removes duplicates but TreeSet does not?

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.

like image 948
blue-sky Avatar asked Feb 13 '13 22:02

blue-sky


People also ask

Does TreeSet remove duplicates?

Features of TreeSet is the primary concern it is widely used in remove duplicates in the data structure as follows: TreeSet implements the SortedSet interface. So, duplicate values are not allowed and will be leftovers. Objects in a TreeSet are stored in a sorted and ascending order.

Does HashSet remove duplicates?

As we know that the HashSet contains only unique elements, ie no duplicate entries are allowed, and since our aim is to remove the duplicate entries from the collection, so for removing all the duplicate entries from the collection, we will use HashSet.

How HashSet eliminate duplicate user defined objects?

The easiest way to remove repeated elements is to add the contents to a Set (which will not allow duplicates) and then add the Set back to the ArrayList: List<String> al = new ArrayList<>(); // add elements to al, including duplicates Set<String> hs = new HashSet<>(); hs. addAll(al); al. clear(); al.

Does Java HashSet store duplicates?

Duplicates: HashSet doesn't allow duplicate values. HashMap stores key, value pairs and it does not allow duplicate keys.


1 Answers

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 equals if it is to correctly implement the Set interface. (See Comparable or Comparator for a precise definition of consistent with equals.) This is so because the Set interface is defined in terms of the equals operation, but a TreeSet instance performs all element comparisons using its compareTo (or compare) method, so two elements that are deemed equal by this method are, from the standpoint of the set, equal. The behavior of a set is well-defined even if its ordering is inconsistent with equals; it just fails to obey the general contract of the Set interface.

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).

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.

like image 70
ruakh Avatar answered Sep 23 '22 05:09

ruakh