以下に示すように2つの異なるハッシュセットがあるとします。2つのハッシュセットが同じ要素を含み、これらの2つのハッシュセットが等しいことを、コレクション内の要素の順序とは無関係に確認するにはどうすればよいですか。
Set set1=new HashSet();
set.add(new Emp("Ram","Trainer",34000));
set.add(new Emp("LalRam","Trainer",34000));
もう1つは..
Set set2=new HashSet();
set.add(new Emp("LalRam","Trainer",34000));
set.add(new Emp("Ram","Trainer",34000));
社員ポジョは...
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;
}*/
}
AbstractSet.equals(Object) javadocからの引用:
指定されたオブジェクトがセットでもあり、2つのセットのサイズが同じで、指定されたセットのすべてのメンバーがこのセットに含まれている場合は、trueを返します。これにより、Setインターフェースの異なる実装間でequalsメソッドが正しく機能することが保証されます。
したがって、set1.equals(set2)
を呼び出すだけで十分です。セットに同じ要素が含まれている場合にのみtrue
を返します(セット内のオブジェクトにequals
とhashCode
を正しく定義した場合)。
次の式を使用します。
set1.containsAll(set2) && set2.containsAll(set1)
イコールとハッシュコードを定義したとすると、ここに1つの方法があります。大きなメンバーにはあまり効率的ではありません。
更新:私はcontainsAllについて知りませんでした。これは多くのトラブルを節約し、基本的にそのアルゴリズムを行います
int s1 = set1.size();
int s2 = set2.size();
if (s1 !=s2) return false;
return set1.containsAll(set2);
データの等価性が必要な場合は、equals()
およびhashCode()
を正しく実装してから、 Collection.containsAll(...) を使用できます。もちろん、両方のコレクションの要素数が同じである場合にのみこれを呼び出す必要があります。そうでない場合は、それらが等しくないと言うことができます。
行う:
setResult = set2.clone();
if ( setResult.retainAll( set1 ) ){
//do something with results, since the collection had differences
}
コレクションのタイプがわからない場合の冗長ですが(うまくいけば)効率的なソリューションです。
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
}
1-1つのコレクションが持っているアイテムと別のコレクションが持っていないアイテムを含むコレクションを取得します(名前を 'differences'とします)-
コレクションの違い= CollectionUtils.subtract(Collection1、Collection2);
2-サイズ== 0であることを確認します。
その場合-両方のコレクションに同じ要素があります。いいえの場合-いくつかの違いがあり、「違い」があるすべてのアイテムを印刷する必要があります。
アイテムの注文に依存するかどうかは不明です。この方法でコレクションを比較しています