1

I need to have data structure like HashSet.

  1. It should not add the same item into the collection
  2. But instead of adding the same item, it should count times this item was added.

As I understand HashSet calculates hashCode at first, if hashCode is the same it checks equals method if true than it will not add an item, otherwise item with the same hashCode but another equals will be added to the bucket linked list.

What I need to do is just keep only unique objects like Set does, but using equals method only, and if objects are equal than increment counter associated with each object.

Is there any such data structure already implemented, or I should create my own ?

  • 2
    You really don't want to use *just* equals, unless you really want to have to check against everything you've already seen on each iteration. It sounds like you just want a `HashMap` to me. – Jon Skeet Jul 06 '16 at 08:14
  • I don't care about hashCode, I only care about equal method, because I need to count how many of the same object (semantically equal using equals method) were added to the `Set`. –  Jul 06 '16 at 08:17
  • 3
    Or, if you can use Guava, a [`Multiset`](https://github.com/google/guava/wiki/NewCollectionTypesExplained). – Andy Turner Jul 06 '16 at 08:18
  • 2
    "I don't care about hashCode, I only care about equal method" [You have to override both if you override one](http://stackoverflow.com/questions/27581/what-issues-should-be-considered-when-overriding-equals-and-hashcode-in-java). – Andy Turner Jul 06 '16 at 08:18
  • @AndyTurner I know that I should but in case of HashMap, because it uses hashCode at first only than equals Multiset is great but I don't want to include full `Guava` library to use only one structure –  Jul 06 '16 at 08:20
  • 2
    To add to Andy's comment - if you don't override `hashCode` in a way that's consistent with `equals`, expect bad things to happen in potentially unexpected places. It's *always* worth making sure that you override them both consistently (or don't override them at all). – Jon Skeet Jul 06 '16 at 08:20
  • @JonSkeet , For example my equals method returns true if user id is the same, should I return user id from the hashcode as well ? –  Jul 06 '16 at 08:22
  • 1
    "should I return user id from the hashcode as well ?" Not necessarily. You should return a hash code derived from the user id, though. – Andy Turner Jul 06 '16 at 08:22
  • 2
    @bkdaaqra you maybe misunderstand the purpose of hash code: it is used to say if two objects are definitely not equal, indicated by the fact that their hash codes are different. If the hashcodes are different, the objects will not be compared using `equals`. – Andy Turner Jul 06 '16 at 08:24
  • @AndyTurner Could you please post all your comments together as an answer explained real purpose of `equals` and `hashCode` , and if it is possible with an example. I would be grateful (not only I) –  Jul 06 '16 at 08:27
  • 1
    There are *plenty* of questions and answers (and other resources) around how hash codes and equality work together. Your question wasn't about the purpose of hash codes - it was about counting items. – Jon Skeet Jul 06 '16 at 08:34

2 Answers2

3

It seems that what you really need is a map. For every item you can have the number of items

public class ItemCounter<T>{

    private Map<T, Integer> counts = new HashMap<T, Integer>();

    public void addItem(T item){
        Integer numberOfOcurrences = counts.get( item );            
        numberOfOcurrences = numberOfOcurrences == null ? 0 : numberOfOcurrences+1;
        counts.put( item,  numberOfOcurrences);            
    }

    public Integer getCount( T item ){
        Integer numberOfOcurrences = counts.get( item );    
        return numberOfOcurrences == null ? 0 : numberOfOcurrences;
    }
}
borjab
  • 11,149
  • 6
  • 71
  • 98
1

The simplest way (without dependecies) is to have a HashMap<Element, Integer>. Or you can use Guava's MultiSet which has a count(Object) method to get the number of occurrences of an object in the collection.

M A
  • 71,713
  • 13
  • 134
  • 174
  • 1
    "So it always checks using equals" - only when it's found candidates whose hash codes match. If you have a set which already has 10 items (hash codes 1...10) and you try to add a new item with hash code 100, it won't call `equals` at all. – Jon Skeet Jul 06 '16 at 08:24