【问题标题】:Avoid Duplicate Records - HashSet避免重复记录 - HashSet
【发布时间】:2013-05-19 09:21:26
【问题描述】:

我正在尝试通过 for 循环将 DTO 的多个对象放入 ArrayList。添加所有对象后,为了避免重复,我将 ArrayList 转换为 HashSet 以避免重复记录。

代码片段 -

....

ArrayList list = new ArrayList();

for( .... ){ 
  Class factory = DTO.getClass();
  Object bean = factory.newInstance();
  list.add(bean);
}

return new ArrayList(new HashSet(list));

但是返回的ArrayList 有重复,我想避免。

【问题讨论】:

    标签: java jakarta-ee arraylist hashset


    【解决方案1】:

    即使您的 DTO 的两个实例包含完全相同的值,它们也会被 HashSet 视为不同。要被视为相等,dto1.equals(dto2)(和 dto2.equals(dto1))必须返回 true。因此,您必须覆盖 DTO 中的 Object.equals() 方法,以便指定两个 DTO 实例何时相等。并且当您覆盖equals() 时,您还必须覆盖hashCode()。两个相等的对象必须具有相同的 hashCode。

    阅读这两种方法的文档,如果您不知道如何实现它们,请使用您的 IDE 生成这两种方法。

    【讨论】:

      【解决方案2】:

      您需要覆盖从 Object 继承的 equals 和 hashcode 方法。 Java 不知道这两个对象是否相等,除非您告诉它要比较什么。 Hashset 类将调用对象的 equals 方法进行比较

      让我们以汽车为例,它有两个字段;类型和颜色。如果两个对象的类型和颜色相同,则它们将被视为相等。

      如果我们不重写 equals 方法,当我们有两个相同的对象时,我们会得到 false

      public class Car {
      
      private String type;
      private String color;
      
      public Car(String type, String color) {
          super();
          this.type = type;
          this.color = color;
      }
      public static void main(String[] args) {
          Car car1 = new Car("Suv","Green");
          Car car2 = new Car("Suv","Green");
          System.out.println(car1.equals(car2)); //false
      }
      

      }

      在这个例子中,我们将告诉 java 我们希望它如何通过覆盖 equals 方法来比较对象

      private String type;
      private String color;
      
      public Car(String type, String color) {
          super();
          this.type = type;
          this.color = color;
      }
      @Override
      public boolean equals(Object obj) { 
          if (this.getClass() == obj.getClass()){
              Car other =(Car)obj;
              if(this.color.equals(other.color) && this.type.equals(other.type)){
                  return true;
              }
          }
          return false;
      }
      public static void main(String[] args) {
          Car car1 = new Car("Suv","Green");
          Car car2 = new Car("Suv","Green");
          System.out.println(car1.equals(car2)); //true
      }
      

      运行这个例子你会得到真实的。

      如果你测试一个没有覆盖等于的对象的哈希集,你将在它们中包含两个类,因为 java 认为它们是不同的对象,因为等于返回 false。用覆盖的方法测试它,你只会有一个

      同样,任何时候你重写equals你也应该重写hashCode。使用您最喜欢的 IDE 来帮助您解决这些问题。

      希望这会有所帮助!

      【讨论】:

        【解决方案3】:

        你应该直接使用接口Set的类。这个避免了定义重复

        http://docs.oracle.com/javase/6/docs/api/java/util/Set.html

        Set list = new HashSet();
        
        for( .... ){ 
            Class factory = DTO.getClass();
            Object bean = factory.newInstance();
            list.add(bean);
        }
        

        【讨论】:

        • 我会推荐 HashSet 而不是 TreeSet,因为它更快(在大多数基本操作中是恒定时间与日志时间),并且不需要保留元素的顺序。
        • 当然,之前刚用过TreeSets,所以习惯了。改了代码
        • 直接使用集合而不是使用中间列表不会使OP的问题消失。
        猜你喜欢
        • 2015-09-12
        • 1970-01-01
        • 2019-11-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-10-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多