【问题标题】:remove Objects from a List base on another list基于另一个列表从列表中删除对象
【发布时间】:2014-10-08 23:04:03
【问题描述】:

我想根据 list2 中的任何内容从列表中删除元素对象列表。 我使用了 removeAll()。 为什么列表没有删除那些在 list2 中找到的元素?

元素.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();
    }
}

【问题讨论】:

    标签: java


    【解决方案1】:

    您需要覆盖Element 类中的equals()hashCode() 方法。

    在这种情况下,您必须重写 equals() 方法。但作为一种好的做法,也可以覆盖 hashCode()

    现在让我们尝试解决您的问题。您可以使用以下equals()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;
    }
    

    更多信息Why do We need to override the equals and hashCode methods in Java?

    【讨论】:

    • 哦,不。如何覆盖这些方法?抱歉我还在学习java
    • 在这种情况下,您不需要重写 hashCode(),但如果您要重写 equals(),建议您重写 hashCode。 docs.oracle.com/javase/7/docs/api/java/lang/…
    • @user3871678 如果您使用 IDE 进行编码,只需生成 equals() 和 hashCode()
    • @Smith_61 我相信覆盖 hashCode 的唯一原因是您打算将这些对象用作 Map 中的键。
    • @alfasin 这是他们推荐它的主要原因。这意味着根据 equals() 相等的对象也必须具有相同的哈希码。 Object.hashCode() 的默认实现不保证这一点。大多数实现都使用 Object 的内存位置,因为它是 hashCode(),但我们不应该知道这一点。
    【解决方案2】:

    因为这些不是同一个元素!每次使用 new 运算符时,您都在创建一个新元素!

    为了使具有相同元素字符串的两个元素相等 - 您必须覆盖(实现)equals() 例如:

    @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());
    }
    

    【讨论】:

    • 没有评论就投反对票是蹩脚的!
    • 不知道是谁投了反对票,但我投了赞成票,因为您的答案包含被不必要地反对的正确信息。
    • 这没有正确保护 NPE。如果 element 为 null 但 o.element 不为 null,则 or 语句的第二个子句将抛出 NPE。
    • @alfasin 抱歉,您不正确。您正在使用 ||不是 &&。假 || true 评估为 true。如果 element == null 和 o.element != null 则第一个条件评估为 false,我们评估第二个条件,此时 this.element 抛出 NPE。如果它是 false && true,我会同意 Java 会缩短评估并避免第二个子句。如果第一个条件评估为真,则第二个评估将被 || 跳过。如果第一个条件为假,第二个条件将被 && 跳过。否则必须评估第二个条件。
    【解决方案3】:

    使用下面的 Element 类应该会对你有所帮助。

    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;
     }
    }
    

    【讨论】:

      【解决方案4】:

      您的 Element 类没有实现 equals。因为他们使用 Object.equals() 方法,该方法只测试它是否是完全相同的对象。 (即它是 == )。

      如果您实现 equals,最好同时实现 hashCode,这样相等的对象将散列到 Map 等哈希数据结构中的同一个桶中。

      这是你的元素,不会有这个问题:

      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();
          }
      }
      

      请注意,我们必须小心元素为空的情况,因为您无法确保该元素具有合理的值。如果合适的话,“更好”的元素类可以避免这种情况,方法是只提供一个接受 String 的构造函数,如果传递给构造函数的字符串为 null,或者如果 setElement 调用采用 null 值,则抛出 IllegalArgumentException。像这样:

      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();
          }
      }
      

      最后,请注意 null == element 比 element == null 更好,因为您很容易忘记等号并最终将 null 分配给 element。如果你写 null = element 编译器会抱怨并提醒你丢弃的字符。

      【讨论】:

        【解决方案5】:

        作为其他答案的替代方案,您可以简单地在两个列表中重复使用相同的对象:

        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());
        }
        

        输出:

        c

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-07-02
          • 1970-01-01
          • 2018-07-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-06-07
          相关资源
          最近更新 更多