0

So, I have two Sets with elements of my class Capability.

public class Capability {
    private String name;

    public Capability(){
        //
    }

    public Capability(String name){
        this.name = name;
        //this.id = count.getAndIncrement();
    }

    public String getName(){
        return name;
    }


    @Override
    public String toString(){
        return "Capability: "+name+".";
    }
}

Please disregard the value of this class over a String, this is for future expansion.

I'm trying to compare two sets that I've gotten from importing a json file, so they are not the same object, nor contain the same object, just have the same content.

public boolean allCapabilitiesMet(){
        int count = 0;
        for(Capability taskCap : this.getReqCapabilities()){
            for(Capability primCap : this.getPrimitive().getCapabilities())
            {
                System.out.println(taskCap.equals(primCap));
                System.out.println(taskCap.getName().equals(primCap.getName()));
                if(taskCap.equals(primCap)){
                    count++;
                }
            }
        }
        return count == this.getReqCapabilities().size();
        //return this.getPrimitive().getCapabilities().containsAll(this.getReqCapabilities());
    }

The goal is to see if one set is a subset of the other, which I could do with the commented return before I switched to importing from the json file.

The thing is, I could fix this right now by simply changing the if clause to the string comparison, because that does indeed work. This would be terrible once I start adding other fields to the main class.

Is there anything I can do to compare the sets content without manually checking their content?

André Rocha
  • 123
  • 7
  • you might just adapt the equals method of your Capability class. For now it should include the name property. If you are adding other fields to that class, just include them in the equals method. You won't even need the nested loops with the count variable - you can simply operate with Set's methods. – juwil Nov 25 '21 at 19:32
  • @juwil i wanted to avoid the for loops entirely and just do something like containsAll(). If it's not possible, well... – André Rocha Nov 25 '21 at 19:34
  • it is possible- but you have to implement the equals (and hashcode btw.) for the members of your Set. – juwil Nov 25 '21 at 19:36
  • 2
    very confusing: title says *"without comparing the content"*, but in question *"compare the sets content wise"* ?!? – user16320675 Nov 25 '21 at 19:37
  • @user16320675 Yes sorry, my question is how to implement something akin to `return this.getPrimitive().getCapabilities().containsAll(this.getReqCapabilities());` without checking the content manually, if possible. If not, what methods should I overwrite – André Rocha Nov 25 '21 at 19:56

1 Answers1

0

So I just replaced the equals() and hashCode() methods in Capability after adding an id field.

@Override
    public boolean equals(Object obj){
        if(this == obj)
            return true;
        
        if(obj == null || obj.getClass() != this.getClass())
            return false;
            
        Capability cap = (Capability) obj;
        return (cap.getName().equals(this.getName()) && cap.getId() == this.getId());    
    }

    @Override
    public int hashCode()
    {
        return (int) this.id;
    }

With this, I can use the solution that I'd originally planned for the comparison

public boolean allCapabilitiesMet(){
        return this.getPrimitive().getCapabilities().containsAll(this.getReqCapabilities());
    }

Is there any issue with this implementation? Sadly, I'll have to add a term to the if statement everytime I want to add a field to Capability. Is there any other way?

André Rocha
  • 123
  • 7
  • First of all, there is equals() and hashCode() [contract](https://www.baeldung.com/java-equals-hashcode-contracts). One of points of the contract is "if two objects are equal, then they must have the same hash code." in your case hashCode can be the same for not equal objects – Alexandr Arhipov Nov 25 '21 at 21:11
  • hashCode is import when you use HashSet or HashMap. Take a look [here](https://stackoverflow.com/questions/6493605/how-does-a-java-hashmap-handle-different-objects-with-the-same-hash-code) – Alexandr Arhipov Nov 25 '21 at 21:12
  • to make the process of generation equals and hashCode easier you can use project lombok [@EqualsAndHashCode](https://projectlombok.org/features/EqualsAndHashCode) – Alexandr Arhipov Nov 25 '21 at 21:16