0

I have actually a problem on a Set in my project (code below)

public static Set<BeanObject> mapToSetBean(Collection<Object> listModel) {
    Set<BeanObject> listToReturn = new HashSet<>();
    for (Iterator<Object> iterator = listModel.iterator(); iterator.hasNext();) {
        Object model = iterator.next();
        BeanObject bean = new BeanObject();
        bean = mapToBean(model);
        listToReturn.add(bean);
    }
    return listToReturn;
}

When some beans are added to the list they replace another one.

For example:

List{}

add object1 / List{object1}

add object2 / List{object1, object2}

add object1 / List{object1, object2, object3}

add object4 / List{object4, object2, object3}

The equals and the hashcode of the object are override the hashcode are all different and in debug mode we don't enter in the override equals.

When I use an ArrayList everything works but I prefer not to change the type it has a huge impact on my project.

---------------- EDIT ---------------

public static BeanObject mapToBean(Object model) {
        BeanObject bean = new BeanObject();
        if (model != null) {
            bean.setId(model.getId());
            
            if(model.getId() != null){
                
                bean.setIdString(model.getId().toString());
            }
            if (model.getName() != null) {
                bean.setName(model.getName().toLowerCase());
            }
            bean.setActif(model.getActif());
            if (model.getShortName() != null) {
                bean.setShortName(model.getShortName().toUpperCase());
            }
            
        }
        return bean;
    }

BeanObject

public class BeanObject implements Comparable<BeanObject> {

    /**
     * serial
     */
    private static final long serialVersionUID = 1L;

    private BigInteger id;

    private String name;

    private String shortName;

    private Short actif;

    private String idString;

    public BeanObject() {
    }

    public BeanObject(BigInteger id, String libelle) {
        this.id = id;
        this.name = libelle;
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @Override
     public boolean equals(Object o) {
    if (o == null) {
        return false;
    }

    if (!(o instanceof BeanObject)) {
        return false;
    }

    BeanObject other = (BeanObject) o;
    boolean result;
    if (null == this.id) {
        if (null == other.id) {
            result = true;
        } else {
            result = false;
        }
    } else {
        result = this.id.equals(other.id);
    }

    return result;
}
 
    /*
     * (non-Javadoc)
     * 
     * @see java.lang.Object#hashCode()
     */
    @Override
    public int hashCode() {
        return this.id.intValue() * name.hashCode() * shortName.hashCode();
    }

    public BigInteger getId() {
        return id;
    }

    public void setId(BigInteger id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getShortName() {
        return shortName;
    }

    public void setShortName(String shortName) {
        this.shortName = shortName;
    }

    public Short getActif() {
        return actif;
    }

    public void setActif(Short actif) {
        this.actif = actif;
    }

    public String getIdString() {
        return idString;
    }

    public void setIdString(String idString) {
        this.idString = idString;
    }
    
}
benj
  • 11
  • 1
  • Welcome to Stack Overflow. Please take the [tour] to learn how Stack Overflow works and read [ask] on how to improve the quality of your question. Then [edit] your question to include the full source code you have as a [mcve], which can be compiled and tested by others. We don't know what the source code of the `BeanObject` class is, you have to add it to your question. – Progman Apr 19 '21 at 18:33
  • Go and check differences between Set and List. – Paweł Głowacz Apr 19 '21 at 18:33
  • You might want to check https://stackoverflow.com/questions/27581/what-issues-should-be-considered-when-overriding-equals-and-hashcode-in-java because your `hashCode()` method implementation breaks the contract described in the javadoc. When you have two objects which are "equals" then your `hashCode()` method must return the same value for both these objects. That is not the case with your implementation. You can have two objects with the same `id` (which results in `equals()` being `true`), but with different `name` and `shortName` values. – Progman Apr 20 '21 at 15:50

1 Answers1

1

Are you certain the BeanObject's hashcode values are unique? That hashcode method seems like it would map a lot of objects to 0 if any of its fields hashed to 0 since it is straight multiplication. I would suggest updating to a more standardized approach for it like the following:

@Override
public int hashCode() {
    return Objects.hash(id, name, shortName);
}

Objects.hash is from the java.util package.

If this still doesn't solve the problem, I would double check the hashcode results for each bean object at add time.

Taugenichts
  • 1,307
  • 12
  • 19
  • 1
    The returned `hashCode()` value doesn't need to be unique for objects which are not equal to each other (might not even be possible depending on the class). – Progman Apr 20 '21 at 15:52
  • I was trying to keep my answer specific to the question. For this code, hashcode is more exclusive than the equals function since equals only checks id whereas hashcode checked those 3 fields I have in my answer. Definitely a good point to consider if this does not solve the question – Taugenichts Apr 20 '21 at 16:23