【问题标题】:Way to check if two Collections contain the same elements, independent of order?检查两个集合是否包含相同元素的方法,与顺序无关?
【发布时间】:2019-01-11 20:48:47
【问题描述】:

假设我有两个不同的哈希集,如下所示如何检查两个哈希集是否包含相同的元素并且这两个哈希集相等,与集合中元素的顺序无关,请指教..!!

Set set1=new HashSet();
          set.add(new Emp("Ram","Trainer",34000));
          set.add(new Emp("LalRam","Trainer",34000));

另一个是..

Set set2=new HashSet();
          set.add(new Emp("LalRam","Trainer",34000));
          set.add(new Emp("Ram","Trainer",34000));

员工 pojo 是...

class Emp //implements Comparable
{
      String name,job;
      public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getJob() {
        return job;
    }
    public void setJob(String job) {
        this.job = job;
    }
    public int getSalary() {
        return salary;
    }
    public void setSalary(int salary) {
        this.salary = salary;
    }
    int salary;
      public Emp(String n,String j,int sal)
      {
         name=n;
         job=j;
         salary=sal;
       }
      public void display()
      {
        System.out.println(name+"\t"+job+"\t"+salary);
       }



  public boolean equals(Object o)
      {

         Emp p=(Emp)o;
          return this.name.equals(p.name)&&this.job.equals(p.job) &&this.salary==p.salary;
       }
   public int hashCode()
       {
          return name.hashCode()+job.hashCode()+salary;
       }


      /* public int compareTo(Object o)
       {
          Emp e=(Emp)o;
          return this.name.compareTo(e.name);
           //return this.job.compareTo(e.job);
        //   return this.salary-e.salary;

        }*/
} 

【问题讨论】:

  • 首先定义“等于”。等于参考还是等价?如果是后者,是否为 Emp 类定义了 equals 和 hashcode?​​span>
  • 假设 Empequals()hashCode() 有适当的覆盖(它可能会这样做,因为它存在于哈希表中)你可以比较集合上的计数,然后尝试添加一个集合的每个元素到另一个集合。如果add() 方法曾经返回true,那么就会有所不同。
  • 这与比较任何其他集合没有什么不同。请参阅:stackoverflow.com/questions/50098/…。虽然这是 .net,但 java 实现应该几乎相同。我推荐 Daniel Jennings 或 mbillings 的回答,因为我很确定投票最高的回答违反了 Microsoft 的使用条款。
  • 首先,在Set 中讨论元素顺序是没有意义的。集合没有隐含的顺序。其次,您没有指定“等于”的含义。对于集合,它可以是“两个集合包含对实际元素的相同引用集”,或“集合 A 中的所有元素比较相等(通过equals())与其对应的元素在集合 B" 中。您似乎想要后一种定义,实现起来比较棘手。
  • 这个问题是重复的,正确答案在这里:stackoverflow.com/questions/1565214/…

标签: java collections hashset


【解决方案1】:

引用AbstractSet.equals(Object)javadoc:

如果给定对象也是一个集合,则返回 true,这两个集合具有 大小相同,并且给定集合的每个成员都包含在该集合中。 这确保了 equals 方法在不同的 Set 接口的实现。

所以只需调用set1.equals(set2) 就足够了。当且仅当集合包含相同的元素时,它将返回true(假设您已在集合中的对象上正确定义了equalshashCode)。

【讨论】:

  • 不错的一个!不知道等于是为集合定义的!
  • 这是正确的答案,比公认的答案简单得多。 +1。
【解决方案2】:

使用下面的表达式。

set1.containsAll(set2) && set2.containsAll(set1)

【讨论】:

  • 我认为这会比做一个包含大小检查前缀的 containsAll 更昂贵。
【解决方案3】:

假设您已经定义了 equals 和 hashcode,这是一种方法。对于大型成员来说效率不是很高。

  1. 检查每个元素的数量。如果他们不相等,你就完了[不相等]。
  2. 循环通过 Set1。检查 Set2 是否包含每个元素,如果没有,则完成 [不等于]。否则,如果你通过整套,你是平等的

更新:我不知道 containsAll,它省了很多麻烦,基本上就是那个算法

int s1 = set1.size();
int s2 = set2.size();
if (s1 !=s2) return false;
return set1.containsAll(set2);

【讨论】:

  • 能否请您发布代码,使理解更清晰..!
  • MJB 能否请您更新完整的代码以使理解清晰..!!
【解决方案4】:

如果您想要数据相等,则正确实现equals()hashCode(),然后您可以使用Collection.containsAll(...)。当然,您需要确保仅当两个集合具有相同数量的元素时才调用此方法,否则您只能说它们不相等。

【讨论】:

  • 太棒了!不记得了。
  • 如果您只知道在哪里查找,您可以在标准 API 中找到很多东西,这真是令人惊讶。 :)
【解决方案5】:

做:

  setResult = set2.clone();

  if ( setResult.retainAll( set1 ) ){

   //do something with results, since the collection had differences

}

【讨论】:

    【解决方案6】:

    1 - 获取一个集合(我们将其命名为“差异”),它将包含一个集合具有而另一个集合没有的项目 -

    集合差异 = CollectionUtils.subtract(Collection1, Collection2);

    2 - 检查 size == 0;

    如果是这样 - 两个集合具有相同的元素; 如果否 - 存在一些差异,然后您必须打印“差异”具有的所有项目。

    不确定是否取决于物品顺序。 我是这样比较集合的

    【讨论】:

      【解决方案7】:

      当您不知道集合的类型时,一个冗长但(希望)有效的解决方案:

      public static <T> boolean equalIgnoreOrder(Collection<T> c1, Collection<T> c2) {
          int size1 = c1.size();  // O(1) for most implementations, but we cache for the exceptions.
          if (size1 != c2.size()) {
              return false;
          }
          Set<T> set;
          Collection<T> other;
          if (c1 instanceof Set) {
              set = (Set<T>) c1;
              other = c2;
          } else if (c2 instanceof Set) {
              set = (Set<T>) c2;
              other = c1;
          } else if (size1 < 12 ) { // N^2 operation OK for small N
              return c1.containsAll(c2);
          } else {
              set = new HashSet<>(c1);
              other = c2;
          }
          return set.containsAll(other);  // O(N) for sets
      }
      

      【讨论】:

        【解决方案8】:

        除非您出于某种原因需要实现自己的方法,否则请使用h1.equals(h2)。下面描述了一种可能的实现方式。

        1. 检查元素数是否相同。如果不是,则返回 false。
        2. 克隆集 2(如果之后需要保留集 2)
        3. 遍历集合 1,检查是否在克隆集合 2 中找到每个元素。如果找到,则从集合 2 中删除。如果没有找到,则返回 false。
        4. 如果您到达迭代的末尾并匹配了集合 1 的每个元素,则集合是相等的(因为您已经比较了 2 个集合的大小)。

        例子:

        public boolean isIdenticalHashSet <A> (HashSet h1, HashSet h2) {
            if ( h1.size() != h2.size() ) {
                return false;
            }
            HashSet<A> clone = new HashSet<A>(h2); // just use h2 if you don't need to save the original h2
            Iterator it = h1.iterator();
            while (it.hasNext() ){
                A = it.next();
                if (clone.contains(A)){ // replace clone with h2 if not concerned with saving data from h2
                    clone.remove(A);
                } else {
                    return false;
                }
            }
            return true; // will only return true if sets are equal
        }
        

        【讨论】:

        • 能否请您发布代码,使理解更清晰..!
        • 这不是一个好的答案,下面的答案应该已经打勾了。
        • set1.equals(set2); 会更好
        • 我不确定为什么这会收到任何反对票。有解释就对了。
        猜你喜欢
        • 2010-12-06
        • 1970-01-01
        • 1970-01-01
        • 2021-06-25
        • 2019-08-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多