Reputation: 23
I want to remove a List of elements Objects from list base on whatever is inside list2. I used removeAll(). Why does the list not remove those elements that are found in list2?
Element.java
public class Element {
private String element;
public Element() {
}
public Element(String element) {
setE(element);
}
public String getElement() {
return element;
}
public void setElement(String element) {
this.element = element;
}
}
RemoveAllTest.java
import java.util.ArrayList;
import java.util.List;
public class RemoveAllTest {
public RemoveAllTest() {
List<Element> list = new ArrayList<Element>();
List<Element> list2 = new ArrayList<Element>();
list.add(new Element("a"));
list.add(new Element("b"));
list.add(new Element("c"));
list2.add(new Element("a"));
list2.add(new Element("b"));
list.removeAll(list2);
for(int i = 0; i < list.size(); i++) {
System.out.println(list.get(i).getElement());
}
}
public static void main(String[] args) {
new RemoveAllTest();
}
}
Upvotes: 0
Views: 111
Reputation: 984
You could, as an alternative to the other answers, simply reuse the same objects in both lists:
Element a = new Element("a");
Element b = new Element("b");
Element c = new Element("c");
list.add(a);
list.add(b);
list.add(c);
list2.add(a);
list2.add(b);
list.removeAll(list2);
for(int i = 0; i < list.size(); i++) {
System.out.println(list.get(i).getElement());
}
output:
c
Upvotes: 0
Reputation: 53525
Because these are not the same elements! every time you're using new
operator you're creating a new element!
In order to make two elements that have the same element string equals - you have to override (implement) equals()
for example:
@Override
public boolean equals(Object other){
if (!( other instanceof Element)) {
return false;
}
Element o = (Element)other;
if (this.element == null) {
return o.getElement() == null;
}
return this.element.equals(o.getElement());
}
Upvotes: 2
Reputation: 2753
Your Element class does not implement equals. Because of they use the Object.equals() method which only tests if it is the exact same object. (i.e. that it is == ).
If you implement equals it is good practice to also implement hashCode so that equal objects will hash into the same bucket in hash data structures like Map.
Here is your Element which will not have this problem:
public class Element {
private String element;
public Element() {
}
public Element(String element) {
setE(element);
}
public String getElement() {
return element;
}
public void setElement(String element) {
this.element = element;
}
public boolean equals(Object other) {
if (other instanceof Element) {
Element otherElement = (Element) other;
if (null == element) {
return otherElement.element == null;
}
return element.equals(otherElement.element);
}
return false;
}
public int hashCode() {
if (null == element) {
return -7;
}
return element.hashCode();
}
}
Note that we have to be careful about cases where element is null because you are not ensuring that element has a sane value. A "better" element class could avoid this if appropriate by only providing a constructor which takes a String and throwing an IllegalArgumentException if the string passed into the constructor is null, or if the setElement call takes a null value. Like so:
public class Element {
private String element;
public Element(String element) {
setElement(element);
}
public String getElement() {
return element;
}
public void setElement(String element) {
if (null == element) {
throw new IllegalArgumentException("Element must not be null.");
}
this.element = element;
}
public boolean equals(Object other) {
if (other instanceof Element) {
Element otherElement = (Element) other;
return element.equals(otherElement.element);
}
return false;
}
public int hashCode() {
return element.hashCode();
}
}
Finally, note that null == element is better to write than element == null since you can easily forget an equal sign and end up assigning null to element. If you write null = element the compiler will complain and alert you of the dropped character.
Upvotes: 2
Reputation: 5868
Use following Element class it should help you.
class Element {
private String element;
public Element() {
}
public Element(String element) {
setElement(element);
}
public String getElement() {
return element;
}
public void setElement(String element) {
this.element = element;
}
public boolean equals(Object object)
{
Element now=(Element)object;
if (object == null || object.getClass() != getClass())
{
result = false;
}
else if(this.getElement().equals(now.getElement()))
{
return true;
}
else
{
return false;
}
}
public int hashCode()
{
if(element!=null)
return element.hashCode();
else
return 0;
}
}
Upvotes: 0
Reputation: 35557
You need to override equals()
and hashCode()
methods in Element
class.
In this case you must override equals()
method. But as a good practice override hashCode()
too.
Now let's try to solve your issue. You can use following as equals()
and hashCode()
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Element)) return false;
Element element1 = (Element) o;
if (element != null ? !element.equals(element1.element)
: element1.element != null) return false;
return true;
}
@Override
public int hashCode() {
return element != null ? element.hashCode() : 0;
}
For more information Why do We need to override the equals and hashCode methods in Java?
Upvotes: 4