Java. ArrayList's contains method not working

2020-05-11 09:21发布

I am checking if ArrayList contains object:

            List<Property> propertiesByName = getPropertiesByCategory(propertyCategory);
        for(Property property: propertiesByName){
            List<Property> propertyList = getVariationItem().getProperties();
            Galgo.log("*******************");
            Galgo.log(propertyList.toString());
            Galgo.log(property.toString());
            Galgo.log("contains:"+propertyList.contains(property));
        }

I am getting following log:

*******************
[Property{name='color', value='red'}, Property{name='size', value='42'}]
Property{name='color', value='red'}
contains:false
*******************
[Property{name='color', value='red'}, Property{name='size', value='42'}]
Property{name='color', value='blue'}
contains:false
Database: get 2 variations
*******************
[Property{name='color', value='red'}, Property{name='size', value='42'}]
Property{name='size', value='42'}
contains:false
*******************
[Property{name='color', value='red'}, Property{name='size', value='42'}]
Property{name='size', value='34'}
contains:false

As you can see in the first and third cases, it should return true. What is wrong?

Other parts of my code. First method to get properties by category(color, size). Second method is to get all available properties:

            private List<Property> getPropertiesByCategory(String category){
            List<Property> properties = new ArrayList<>();
            for(Property property: getAllProperties()){
                if(property.getName().equals(category)){
                    if(!properties.contains(property)){
                        properties.add(property);
                    }
                }
            }
            return properties;
        }

        private List<Property> getAllProperties() {
            List<Property> propertyList = new ArrayList<>();
            for(VariationItem variationItem: getProductItem().getVariationsList()){
                for(Property property: variationItem.getProperties()){
                    if(!propertyList.contains(property))
                    {
                        propertyList.add(property);
                    }
                }
            }
            return propertyList;
        }

2条回答
戒情不戒烟
2楼-- · 2020-05-11 09:57

To use contains method, you have to override equals() and hashCode() methods to achieve this. You can check this answer for implementation https://stackoverflow.com/a/16069158/1320616. Actually contains() will compare two objects. And to compare two objects you have to implement equals() method.

Edit : Here are the full details

So when you use contains() what it is doing is

@Override public boolean contains(Object object) {
        Object[] a = array;
        int s = size;
        if (object != null) {
            for (int i = 0; i < s; i++) {
                if (object.equals(a[i])) {
                    return true;
                }
            }
        } else {
            for (int i = 0; i < s; i++) {
                if (a[i] == null) {
                    return true;
                }
            }
        }
        return false;
    }

and if you don't implement equals() method in your class it will take the equals() method from the Object class which is

public boolean equals(Object o) {
        return this == o;
}

So now it reduces to == is being used between two objects to compare them. When you put == between two objects, it compares on basis of two things (a) hashcodes of two objects (b) It uses toString() of the two objects.

Each object has different hashcodes assigned to them. this is the reason why your contains() is not giving you correct results.

查看更多
成全新的幸福
3楼-- · 2020-05-11 09:58

you can check as String like this:

 Galgo.log("contains:"+propertyList.toString().contains(property.toString()));
查看更多
登录 后发表回答