如何删除List <MyObject>中没有equals/hashcode的重复对象?

Die*_*ria 27 java collections

我必须删除列表中的重复对象.它是来自对象Blog的List,如下所示:

public class Blog {
    private String title;
    private String author;
    private String url;
    private String description;
    ...
}
Run Code Online (Sandbox Code Playgroud)

复制对象是一个对象,其标题,作者,URL和描述等于其他对象.

我无法改变这个对象.我不能把新的方法放在上面.

我该怎么做呢?

San*_*eep 17

以下是适用于此场景的完整代码:

class Blog {
    private String title;
    private String author;
    private String url;
    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    private String description;    

    Blog(String title, String author, String url, String description)
    {
        this.title = title;
        this.author = author;
        this.url = url;
        this.description = description; 
    }
    @Override
    public boolean equals(Object obj) {
        // TODO Auto-generated method stub
        if(obj instanceof Blog)
        {
            Blog temp = (Blog) obj;
            if(this.title == temp.title && this.author== temp.author && this.url == temp.url && this.description == temp.description)
                return true;
        }
        return false;

    }
    @Override
    public int hashCode() {
        // TODO Auto-generated method stub

        return (this.title.hashCode() + this.author.hashCode() + this.url.hashCode() + this.description.hashCode());        
    }
}
Run Code Online (Sandbox Code Playgroud)

}

这是主要功能,将消除重复:

public static void main(String[] args) {
    Blog b1 = new Blog("A", "sam", "a", "desc");
    Blog b2 = new Blog("B", "ram", "b", "desc");
    Blog b3 = new Blog("C", "cam", "c", "desc");
    Blog b4 = new Blog("A", "sam", "a", "desc");
    Blog b5 = new Blog("D", "dam", "d", "desc");
    List<Blog> list = new ArrayList();
    list.add(b1);
    list.add(b2);
    list.add(b3);
    list.add(b4);       
    list.add(b5);

    //Removing Duplicates;
    Set<Blog> s= new HashSet<Blog>();
    s.addAll(list);         
    list = new ArrayList<Blog>();
    list.addAll(s);        
    //Now the List has only the identical Elements
}
Run Code Online (Sandbox Code Playgroud)

}

  • 您正在将字符串与 == 进行比较。应该是 this.title.equals(temp.title)..... (4认同)

mat*_*t b 12

如果你不能编辑类的源代码(为什么不呢?),那么你需要迭代列表并根据提到的四个标准("标题,作者,网址和描述")比较每个项目.

要做到这一点的性能方法,我会创建一个新的类,像BlogKey它包含那些四种元素和其正确实施equals()hashCode().然后,您可以遍历原始列表,BlogKey为每个列表构建一个并添加到HashMap:

Map<BlogKey, Blog> map = new HashMap<BlogKey, Blog>();
for (Blog blog : blogs) {
     BlogKey key = createKey(blog);
     if (!map.containsKey(key)) {
          map.put(key, blog);
     }
}
Collection<Blog> uniqueBlogs = map.values();
Run Code Online (Sandbox Code Playgroud)

然而,最简单的方法是编辑原始源代码,Blog以便正确实现equals()hashCode().

  • 就个人而言,我会质疑一个生成像这样的实体类的工具的实用程序并且没有实现equals()或hashcode(),因为看起来这个类会在很多其他方面被打破 - 但是YMMV. (5认同)
  • 因为它是 MyBatis 生成的一个类,每次数据库改变时都会重新生成,所以我不能改变这个类。而且我无法创建另一个类,因为我有十多个类来执行此操作。但我想我会使用地图,但键将是四个字段的串联。谢谢!很有用!!解决了我的问题!再次感谢!:) (2认同)
  • 使用 http://www.mybatis.org/generator/apidocs/reference/org/mybatis/generator/plugins/EqualsHashCodePlugin.html 生成 MyBatis `equals` 和 `hashCode` (2认同)

Chr*_*röm 10

确保Blog有方法equals(Object)hashCode()定义,addAll(list)然后到a new HashSet(),或者new LinkedHashSet()顺序是否重要.

更好的是,从一开始就使用a Set而不是a List,因为你显然不想要重复,所以你的数据模型更好地反映了它,而不是必须在事后删除它们.


Ale*_*exR 8

使用集:

yourList = new ArrayList<Blog>(new LinkedHashSet<Blog>(yourList));

这将创建没有重复的列表,元素顺序将与原始列表相同。

只是不要忘记为您的班级博客实现hashCode()equals()。