【问题标题】:How to remove duplicate objects in a List<MyObject> without equals/hashcode?如何在没有等于/哈希码的 List<MyObject> 中删除重复的对象?
【发布时间】:2011-10-04 13:00:09
【问题描述】:

我必须删除列表中的重复对象。 它是对象博客中的一个列表,如下所示:

public class Blog {
    private String title;
    private String author;
    private String url;
    private String description;
    ...
}

重复对象是具有与其他对象相同的标题、作者、url 和描述的对象。

而且我无法更改对象。我不能在上面放新方法。

我该怎么做?

【问题讨论】:

  • equals 方法是否已经被覆盖?

标签: java collections


【解决方案1】:
  1. 使用这 4 个字段覆盖 hashCode()equals(..)
  2. 使用new HashSet&lt;Blog&gt;(blogList) - 这将给你一个Set,根据定义没有重复

更新:由于你不能更改类,这里有一个 O(n^2) 的解决方案:

  • 创建一个新列表
  • 迭代第一个列表
  • 在内循环中迭代第二个列表并验证它是否具有具有相同字段的元素

如果您提供具有外部化hashCode()equals(..) 方法的HashSet 数据结构,则可以提高效率。

【讨论】:

  • 我无法编辑对象的类,我如何在不改变对象的情况下做到这一点?
【解决方案2】:

确保 Blog 定义了 equals(Object)hashCode() 方法,然后将 addAll(list) 定义为 new HashSet()new LinkedHashSet()(如果订单很重要)。

更好的是,从一开始就使用Set 而不是List,因为您显然不希望重复,因此您的数据模型最好能反映这一点,而不是事后删除它们。

【解决方案3】:

如果您的Blog 类上定义了适当的equals() 方法,最简单的方法就是从您的列表中创建一个Set,它会自动删除重复项:

List<Blog> blogList = ...; // your initial list
Set<Blog> noDups = new HashSet<Blog>(blogList)

这很可能会与您的其余代码透明地工作 - 例如,如果您只是迭代内容,那么Collection 的任何实例都与另一个实例一样好。 (如果迭代顺序很重要,那么您可能更喜欢 LinkedHashSet,这将保留列表的原始顺序)。

如果您确实需要将结果设为List,那么请保持直接的方法,您可以通过包装ArrayList(或类似的)再次将其直接转换回来。如果您的集合相对较小(例如,少于一千个元素),那么这种方法的明显低效可能并不重要。

【讨论】:

  • 我无法编辑对象的类,我如何在不改变对象的情况下做到这一点?
【解决方案4】:

使用集:

yourList = new ArrayList&lt;Blog&gt;(new LinkedHashSet&lt;Blog&gt;(yourList));

这将创建没有重复的列表,并且元素顺序将与原始列表中的一样。

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

【讨论】:

  • 我无法编辑对象的类,我如何在不改变对象的情况下做到这一点?
【解决方案5】:

首先覆盖equals()方法:

@Override
public boolean equals(Object obj)
{
    if(obj == null) return false;
    else if(obj instanceof MyObject && getTitle() == obj.getTitle() && getAuthor() == obj.getAuthor() && getURL() == obj.getURL() && getDescription() == obj.getDescription()) return true;
    else return false;
}

然后使用:

List<MyObject> list = new ArrayList<MyObject>;
for(MyObject obj1 : list)
{
    for(MyObject obj2 : list)
    {
        if(obj1.equals(obj2)) list.remove(obj1); // or list.remove(obj2);
    }
}

【讨论】:

  • 这是非常低效的。 O(N^2) 或更糟。更不用说不正确,因为Arrays.deepEquals() 将数组作为参数。
  • @Christoffer 你完全正确,但这是我首先想到的。
  • 您不能将字符串与== 进行比较!如果我有另一个-1可以给我。
【解决方案6】:

您可以使用标题、作者、网址和描述覆盖equals() 方法。 (和hashCode(),因为如果你覆盖一个,你应该覆盖另一个)。然后使用&lt;blog&gt; 类型的HashSet

【讨论】:

  • 我无法编辑对象的类,我如何在不改变对象的情况下做到这一点?
【解决方案7】:

您需要的第一步是实现 equals 方法并比较您的字段。之后,步骤会有所不同。

您可以使用 if(!list2.contains(item)) 创建一个新的空列表并循环遍历原始列表,然后进行添加。

另一种快速的方法是将它们全部塞入一个 Set 中,然后将它们拉回一个 List 中。这是可行的,因为 Sets 不允许以重复开头。

【讨论】:

  • 错了! Comparable 不适用于 Set(您可以自己尝试)。对于一组,您需要equalshashcode
  • 遥遥领先!在我写完大约 30 秒后修复它!虽然很好,但在未排序的集合中没有什么可比较的。
【解决方案8】:

而且我无法更改对象。我不能把新方法放在上面。

我该怎么做?

如果您还指我如何使对象不可变并防止子类化:使用 final 关键字

public final class Blog { //final classes can't be extended/subclassed
   private final String title; //final members have to be set in the constructor and can't be changed
   private final String author;
   private final String url;
   private final String description;
    ...
}

编辑:我刚刚看到您的一些 cmets,您似乎想更改课程但不能(我假设是第三方)。

为防止重复,您可以使用实现适当equals()hashCode() 的包装器,然后使用其他人提到的Set 方法:

 class BlogWrapper {
   private Blog blog; //set via constructor etc.

   public int hashCode() {
     int hashCode = blog.getTitle().hashCode(); //check for null etc.
     //add the other hash codes as well
     return hashCode;
   }

   public boolean equals(Object other) {
     //check if both are BlogWrappers
     //remember to check for null too!
     Blog otherBlog = ((BlogWrapper)other).getBlog(); 
     if( !blog.getTitle().equals(otherBlog.getTitle()) {
       return false;
     }
     ... //check other fields as well
     return true
   }
 }

请注意,这只是一个粗略和简单的版本,不包含强制性的空检查。

最后使用Set&lt;BlogWrapper&gt;,遍历所有博客并尝试将new BlogWrapper(blog) 添加到集合中。最后,您应该只在集合中拥有独特(包装)的博客。

【讨论】:

  • 不,抱歉...我是说我必须在不添加方法 equals 和 hashCode 的情况下删除 Blog 对象列表中的重复项,因为我无法更改此方法。
  • @Diego 看看我的回答,我说提供一个你可以编写的包装器。这不会改变 Blog 类本身。
【解决方案9】:

如果您不能编辑类的源代码(为什么不能?),那么您需要遍历列表并根据提到的四个标准(“标题、作者、网址和描述”)比较每个项目。

要以高效的方式执行此操作,我将创建一个新类,例如 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();

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

【讨论】:

  • 因为它是MyBatis生成的一个类,而且每次更改数据库时都会重新生成,所以我不能改变这个类。而且我不能创建另一个班级,因为我还有十个班级要这样做。但我想我会使用地图,但关键将是四个字段的串联。谢谢!很有用!!解决了我的问题!再次感谢! :)
  • 就我个人而言,我会质疑生成这样的实体类并且不实现 equals() 或 hashcode() 的工具的实用性,因为看起来这个类会在很多情况下被破坏其他方式 - 但 YMMV。
  • 是否可以像在 C# 中使用 LINQ 那样在 lambda 表达式中执行此操作?
  • @DiegoFaria 我建议不要使用字段值的连接,因为它容易出错:2 个不同的标题和作者值最终可能会连接到同一个字符串。但是,您可能想要做的是仅使用键的 hashCode() 实现中的 url 以及 equals() 实现中的所有字段。这样一来,如果在将部分键放入地图后更改了部分键,您就不会遇到麻烦。
【解决方案10】:

创建一个新类来包装您的 Blog 对象并提供您需要的相等/哈希码方法。为了获得最大效率,我将在包装器上添加两个静态方法,一个用于转换博客列表 -> 博客包装器列表,另一个用于转换博客包装器列表 -> 博客列表。那么你会:

  1. 将您的博客列表转换为博客包装列表
  2. 将您的博客包装列表添加到哈希集
  3. 从哈希集中取出精简的博客包装列表
  4. 将博客包装器列表转换为博客列表

Blog Wrapper 的代码是这样的:

import java.util.ArrayList;
import java.util.List;

public class BlogWrapper {
    public static List<Blog> unwrappedList(List<BlogWrapper> blogWrapperList) {
        if (blogWrapperList == null)
            return new ArrayList<Blog>(0);

        List<Blog> blogList = new ArrayList<Blog>(blogWrapperList.size());
        for (BlogWrapper bW : blogWrapperList) {
            blogList.add(bW.getBlog());
        }

        return blogList;
    }

    public static List<BlogWrapper> wrappedList(List<Blog> blogList) {
        if (blogList == null)
            return new ArrayList<BlogWrapper>(0);

        List<BlogWrapper> blogWrapperList = new ArrayList<BlogWrapper>(blogList
                .size());
        for (Blog b : blogList) {
            blogWrapperList.add(new BlogWrapper(b));
        }

        return blogWrapperList;
    }

    private Blog blog = null;

    public BlogWrapper() {
        super();
    }

    public BlogWrapper(Blog aBlog) {
        super();
        setBlog(aBlog);
    }

    public boolean equals(Object other) {
        // Your equality logic here
        return super.equals(other);
    }

    public Blog getBlog() {
        return blog;
    }

    public int hashCode() {
        // Your hashcode logic here
        return super.hashCode();
    }

    public void setBlog(Blog blog) {
        this.blog = blog;
    }
}

你可以这样使用:

List<BlogWrapper> myBlogWrappers = BlogWrapper.wrappedList(your blog list here);
Set<BlogWrapper> noDupWrapSet = new HashSet<BlogWrapper>(myBlogWrappers);
List<BlogWrapper> noDupWrapList = new ArrayList<BlogWrapper>(noDupSet);
List<Blog> noDupList = BlogWrapper.unwrappedList(noDupWrapList);

很明显,您可以使上述代码更高效,特别是通过使 Blog Wrapper 上的 wrap 和 unwrap 方法采用集合而不是 List。

包装 Blog 类的另一种方法是使用像 BCEL 这样的字节码操作库来实际更改 Blog 的 equals 和 hashcode 方法。但是,当然,如果它们需要原始的 equals/hashcode 行为,这可能会对您的其余代码产生意想不到的后果。

【讨论】:

    【解决方案11】:

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

    class Blog {
        private String title;
        private String author;
        private String url;
        private String description; 
    
        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;
        }
    
        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.equals(temp.title) && this.author.equals(temp.author) && this.url.equals(temp.url) && this.description.equals(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());        
        }
    }
    

    这是消除重复的主要功能:

    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
    }
    

    【讨论】:

    • 您正在将字符串与 == 进行比较。应该是this.title.equals(temp.title).....
    【解决方案12】:

    我尝试了几种方法来从 java 对象列表中删除重复项
    其中一些是
    1. 覆盖 equals 和 hashCode 方法,并通过将列表传递给集合类构造函数并将列表转换为集合并删除并添加所有
    2. 运行 2 个指针并删除通过运行 2 个 for 循环手动重复,就像我们以前在 C 语言中为数组所做的那样,一个在另一个循环中
    3.为 bean 编写一个匿名 Comparator 类并执行 Collections.sort,然后运行 ​​2 个指针以向前删除.



    而且我的要求是从近 500 万个对象中删除近 100 万个重复项。
    因此,经过多次试验,我最终选择了第三个选项,我认为这是最有效的方法,结果证明是在内部进行评估秒,而其他 2 个选项几乎需要 10 到 15 分钟。
    第一个和第二个选项非常无效,因为当我的对象增加时,删除重复项所需的时间以指数方式增加。

    所以最后是第三个选择是最好的。

    【讨论】:

      【解决方案13】:

      最简单和最有效的方法是让 eclipse 生成和覆盖 equals 和 hashcode 方法。只需在出现提示时选择要检查重复项的属性,您就应该一切就绪。

      同样,一旦列表准备好,将其放入 Set 中,重复项就消失了。

      【讨论】:

        【解决方案14】:
            import java.util.ArrayList;
        
            import java.util.HashSet;
        
            class Person
        
        {
            public int age;
            public String name;
            public int hashCode()
            {
               // System.out.println("In hashcode");
                int hashcode = 0;
                hashcode = age*20;
                hashcode += name.hashCode();
                System.out.println("In hashcode :  "+hashcode);
                return hashcode;
            }
             public boolean equals(Object obj)
                {
                    if (obj instanceof Person)
                        {
                            Person pp = (Person) obj;
                            boolean flag=(pp.name.equals(this.name) && pp.age == this.age); 
                            System.out.println(pp);
                            System.out.println(pp.name+"    "+this.name);
                            System.out.println(pp.age+"    "+this.age);
                            System.out.println("In equals : "+flag);
                            return flag;
                        }
                        else 
                            {
                            System.out.println("In equals : false");
                                return false;
                            }
                 }
            public void setAge(int age)
            {
                this.age=age;
            }
            public int getAge()
            {
                return age;
            }
            public void setName(String name )
            {
                this.name=name;
            }
            public String getName()
            {
                return name;
            }
            public String toString()
            {
                return "[ "+name+", "+age+" ]";
            }
        }
        class ListRemoveDuplicateObject 
        {
            public static void main(String[] args) 
            {
                ArrayList<Person> al=new ArrayList();
                
                    Person person =new Person();
                    person.setName("Neelesh");
                    person.setAge(26);
                    al.add(person);
                    
                    person =new Person();
                    person.setName("Hitesh");
                    person.setAge(16);
                    al.add(person);
                
                    person =new Person();
                    person.setName("jyoti");
                    person.setAge(27);
                    al.add(person);
                    
                    person =new Person();
                    person.setName("Neelesh");
                    person.setAge(60);
                    al.add(person);
                    
                    person =new Person();
                    person.setName("Hitesh");
                    person.setAge(16);
                    al.add(person);
        
                    person =new Person();
                    person.setName("Mohan");
                    person.setAge(56);
                    al.add(person);
                    
                    person =new Person();
                    person.setName("Hitesh");
                    person.setAge(16);
                    al.add(person);
        
                System.out.println(al);
                HashSet<Person> al1=new HashSet();
                al1.addAll(al);
                al.clear();
                al.addAll(al1);
                System.out.println(al);
            }
        }
        

        输出

        [[ Neelesh, 26 ], [ Hitesh, 16 ], [ jyoti, 27 ], [ Neelesh, 60 ], [ Hitesh, 16 ], [ Mohan,56 ], [ Hitesh, 16 ]]
        
        In hashcode :  -801018364
        In hashcode :  -2133141913
        In hashcode :  101608849
        In hashcode :  -801017684
        In hashcode :  -2133141913
        [ Hitesh, 16 ]
        Hitesh    Hitesh
        16    16
        In equals : true
        In hashcode :  74522099
        In hashcode :  -2133141913
        [ Hitesh, 16 ]
        Hitesh    Hitesh
        16    16
        In equals : true
        [[ Neelesh, 60 ], [ Neelesh, 26 ], [ Mohan, 56 ], [ jyoti, 27 ], [ Hitesh, 16 ]]
        

        【讨论】:

        • 这段代码说明了如何以改变类的方式实现equals和hash。问题坚持你不要改变班级。
        【解决方案15】:

        这是删除重复对象的一种方法。

        博客类应该是这样或类似的,比如适当的 pojo

        public class Blog {
        
            private String title;
            private String author;
            private String url;
            private String description;
        
            private int hashCode;
        
        
        
            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;
            }
        
            @Override
            public boolean equals(Object obj) {
        
                Blog blog = (Blog)obj;
        
                if(title.equals(blog.title) &&
                        author.equals(blog.author) &&
                        url.equals(blog.url) &&
                        description.equals(blog.description))
                {
                    hashCode = blog.hashCode;
                    return true;
                }else{
                    hashCode = super.hashCode();
                    return false;
                }
            }
        
        }
        

        并像这样使用它来删除重复的对象。这里的关键数据结构是 Set 和 LinkedHashSet。它将删除重复项并保持输入顺序

            Blog blog1 = new Blog();
            blog1.setTitle("Game of Thrones");
            blog1.setAuthor("HBO");
            blog1.setDescription("The best TV show in the US");
            blog1.setUrl("www.hbonow.com/gameofthrones");
        
            Blog blog2 = new Blog();
            blog2.setTitle("Game of Thrones");
            blog2.setAuthor("HBO");
            blog2.setDescription("The best TV show in the US");
            blog2.setUrl("www.hbonow.com/gameofthrones");
        
            Blog blog3 = new Blog();
            blog3.setTitle("Ray Donovan");
            blog3.setAuthor("Showtime");
            blog3.setDescription("The second best TV show in the US");
            blog3.setUrl("www.showtime.com/raydonovan");
        
            ArrayList<Blog> listOfBlogs = new ArrayList<>();
        
            listOfBlogs.add(blog1);
            listOfBlogs.add(blog2);
            listOfBlogs.add(blog3);
        
        
            Set<Blog> setOfBlogs = new LinkedHashSet<>(listOfBlogs);
        
            listOfBlogs.clear();
            listOfBlogs.addAll(setOfBlogs);
        
            for(int i=0;i<listOfBlogs.size();i++)
                System.out.println(listOfBlogs.get(i).getTitle());
        

        运行这个应该打印

        Game of Thrones
        Ray Donovan
        

        第二个将被删除,因为它是第一个对象的副本。

        【讨论】:

          【解决方案16】:

          使用此代码

           public List<Blog> removeDuplicates(List<Blog> list) {
              // Set set1 = new LinkedHashSet(list);
              Set set = new TreeSet(new Comparator() {
          
                  @Override
                  public int compare(Object o1, Object o2) {
                      if (((Blog) o1).get().equalsIgnoreCase(((Blog) o2).getId()) /*&&
                              ((Blog)o1).getName().equalsIgnoreCase(((Blog)o2).getName())*/) {
                          return 0;
                      }
                      return 1;
                  }
              });
              set.addAll(list);
          
              final List newList = new ArrayList(set);
              return newList;
          }
          

          【讨论】:

          • compare() 接口的Comparator 函数用于排序和删除重复项。您必须使用equalshashCode 函数来确定两个对象是否相等。
          【解决方案17】:

          建议覆盖equals()hashCode() 以使用基于哈希的集合,包括HashMapHashSetHashtable,因此您可以通过启动HashSet 轻松删除重复项带有博客列表的对象。

          List<Blog> blogList = getBlogList();
          Set<Blog> noDuplication = new HashSet<Blog>(blogList);
          

          但是感谢 Java 8 有非常干净的版本来执行此操作,正如您提到的,您无法更改代码以添加 equals()hashCode()

          Collection<Blog> uniqueBlogs = getUniqueBlogList(blogList);
          
          private Collection<Blog> getUniqueBlogList(List<Blog> blogList) {
              return blogList.stream()
                      .collect(Collectors.toMap(createUniqueKey(), Function.identity(), (blog1, blog2) -> blog1))
                      .values();
          }
          List<Blog> updatedBlogList = new ArrayList<>(uniqueBlogs);
          

          Collectors.toMap()的第三个参数是merge函数(函数式接口),用于解决同一个key关联的值之间的冲突。

          【讨论】:

            【解决方案18】:

            这可以使用属性从逻辑上解决。在这里,我有一个称为键的属性。

            1. 取出对象中的任意String属性,放入列表中。
            2. 检查该属性包含的天气列表,如果是,则将其删除。
            3. 返回对象列表。

            List<Object> objectList = new ArrayList<>();
             List<String> keyList = new ArrayList<>();
              objectList.forEach( obj -> {
               if(keyList.contains(unAvailabilityModel.getKey())) 
                     objectList.remove(unAvailabilityModel); 
                else
                    keyList.add(unAvailabilityModel.getKey();
            });
            return objectList;
            

            【讨论】:

            • 您的示例需要一些工作。您正在删除您正在循环的列表中的项目,因此您将得到一个java.util.ConcurrentModificationException,假设它不为空。如果它是空的,它就不会做任何事情。
            【解决方案19】:

            我们还可以使用 Comparator 来检查重复元素。示例代码如下,

            private boolean checkDuplicate(List studentDTOs){

                Comparator<StudentDTO > studentCmp = ( obj1,  obj2)
                        ->{
                    if(obj1.getName().equalsIgnoreCase(obj2.getName())
                            && obj1.getAddress().equalsIgnoreCase(obj2.getAddress())
                            && obj1.getDateOfBrith().equals(obj2.getDateOfBrith())) {
                        return 0;
                    }
                    return 1;
                };
                Set<StudentDTO> setObj = new TreeSet<>(studentCmp);
                setObj.addAll(studentDTOs);
                return setObj.size()==studentDTOs.size();
            }
            

            【讨论】:

              【解决方案20】:

              如果由于某些原因您不想覆盖 equals 方法并且想要删除基于多个属性的重复项,那么我们可以创建一个通用方法来执行此操作。

              我们可以写成2个版本:

              1.修改原列表:

              @SafeVarargs
              public static <T> void removeDuplicatesFromList(List<T> list, Function<T, ?>... keyFunctions) {
              
                  Set<List<?>> set = new HashSet<>();
              
                  ListIterator<T> iter = list.listIterator();
                  while(iter.hasNext()) {
                      T element = iter.next();
              
                      List<?> functionResults = Arrays.stream(keyFunctions)
                              .map(function -> function.apply(element))
                              .collect(Collectors.toList());
              
                      if(!set.add(functionResults)) {
                          iter.remove();
                      }
                  }
              }
              

              2。返回一个新列表:

              @SafeVarargs
              public static <T> List<T> getListWithoutDuplicates(List<T> list, Function<T, ?>... keyFunctions) {
              
                  List<T> result = new ArrayList<>();
              
                  Set<List<?>> set = new HashSet<>();
              
                  for(T element : list) {
                      List<?> functionResults = Arrays.stream(keyFunctions)
                              .map(function -> function.apply(element))
                              .collect(Collectors.toList());
              
                      if(set.add(functionResults)) {
                          result.add(element);
                      }
                  }
              
                  return result;
              }
              

              在这两种情况下,我们都可以考虑任意数量的属性。

              例如,根据titleauthorurldescription 4 个属性删除重复项:

              removeDuplicatesFromList(blogs, Blog::getTitle, Blog::getAuthor, Blog::getUrl, Blog::getDescription);
              

              这些方法通过利用Listequals 方法工作,该方法将检查其元素的相等性。在我们的例子中,functionResults 的元素是从传递的 getter 中检索到的值,我们可以使用该列表作为 Set 的元素来检查重复项。

              完整示例:

              public class Duplicates {
              
                  public static void main(String[] args) {
              
                      List<Blog> blogs = new ArrayList<>();
                      blogs.add(new Blog("a", "a", "a", "a"));
                      blogs.add(new Blog("b", "b", "b", "b"));
                      blogs.add(new Blog("a", "a", "a", "a"));    // duplicate
                      blogs.add(new Blog("a", "a", "b", "b"));
                      blogs.add(new Blog("a", "b", "b", "b"));
                      blogs.add(new Blog("a", "a", "b", "b"));    // duplicate
              
                      List<Blog> blogsWithoutDuplicates = getListWithoutDuplicates(blogs, 
                              Blog::getTitle, Blog::getAuthor, Blog::getUrl, Blog::getDescription);
                      System.out.println(blogsWithoutDuplicates); // [a a a a, b b b b, a a b b, a b b b]
                      
                      removeDuplicatesFromList(blogs, 
                              Blog::getTitle, Blog::getAuthor, Blog::getUrl, Blog::getDescription);
                      System.out.println(blogs);                  // [a a a a, b b b b, a a b b, a b b b]
                  }
              
                  private static class Blog {
                      private String title;
                      private String author;
                      private String url;
                      private String description;
              
                      public Blog(String title, String author, String url, String description) {
                          this.title = title;
                          this.author = author;
                          this.url = url;
                          this.description = description;
                      }
              
                      public String getTitle() {
                          return title;
                      }
              
                      public String getAuthor() {
                          return author;
                      }
              
                      public String getUrl() {
                          return url;
                      }
              
                      public String getDescription() {
                          return description;
                      }
              
                      @Override
                      public String toString() {
                          return String.join(" ", title, author, url, description);
                      }
                  }
              }
              

              【讨论】:

                【解决方案21】:

                您可以使用 distinct 删除重复项

                List<Blog> blogList = ....// add your list here
                
                blogList.stream().distinct().collect(Collectors.toList());
                
                

                【讨论】:

                • 这个解决方案只有在Blog对象实现equals方法时才有效。
                • 欢迎来到 Stack Overflow。您能否编辑您的答案以解释您的方法与先前存在的答案有何不同 - 至少,the accepted answerthe popular alternative?为什么读者应该考虑这种方法而不是高度验证的答案之一?
                猜你喜欢
                • 1970-01-01
                • 2023-04-09
                • 1970-01-01
                • 2015-09-13
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2018-07-24
                • 1970-01-01
                相关资源
                最近更新 更多