26

私は2つStringの配列を持っています、例えば:

String[] s1 = {"a","b","c"}
String[] s2 = {"c","a","b"} 

//これらの配列は等しくなければなりません

私は彼らの平等を「最もクリーンな」方法でチェックしたかったのです。

使ってみArrays.equals(s1,s2)ましたが、間違った答えが返ってきます。この方法は要素の順序を気にするので、それは問題にならないようにしたいと思います。

どうすればいい方法でそれができるか教えていただけますか?

4

10 に答える 10

32
  • Arrays.sort(s1);
  • Arrays.sort(s2);
  • Arrays.equals(s1、s2);

元の配列を変更したくない場合

 Arrays.equals( Arrays.sort( Arrays.copyof(s1,s1.length)),
                Arrays.sort( Arrays.copyof(s2,s2.length)) );

Arrays.sort()は、最適化されたクイックソートを使用します。これは、平均ではnlog(n)ですが、最悪の場合はO(n2)です。Javaドキュメントから。したがって、最悪の場合はO(n2)になりますが、実際にはほとんどの場合O(nlogn)になります。

ソートアルゴリズムは、JonL.BentleyとM.DouglasMcIlroyの「EngineeringaSortFunction」、Software-Practice and Experience、Vol。23(11)P. 1249-1265(1993年11月)。このアルゴリズムは、多くのデータセットでn * log(n)のパフォーマンスを提供し、他のクイックソートのパフォーマンスを2次パフォーマンスに低下させます。

于 2012-04-14T14:25:22.993 に答える
12

他の人は、配列をソートすることを提案しました。しかし、あなたは「最もクリーンな」ソリューションを探しているので、元のアレイに手を加えるべきではないと思います。したがって:

List<String> l1 = new ArrayList<String>(Arrays.asList(s1));
List<String> l2 = new ArrayList<String>(Arrays.asList(s2));

Collections.sort(l1);
Collections.sort(l2);

boolean outcome = l1.equals(l2);
于 2012-04-14T14:31:12.113 に答える
4

Eclipseコレクションを使用している場合は、を使用しBagて2つの配列が等しいかどうかを判断できます。

String[] s1 = {"a", "b", "c", "c"};
String[] s2 = {"c", "a", "b", "c"};

Bag<String> h1 = Bags.mutable.with(s1);
Bag<String> h2 = Bags.mutable.with(s2);
Assert.assertEquals(h1, h2);

バッグ(マルチセットとも呼ばれます)は、各要素の出現回数が同じである場合、等しいと見なされます。順序は重要ではなく、重複する要素を適切に処理します。ハッシュテーブルに裏打ちされたバッグを使用する利点は、バッグの作成に直線的な時間がかかることです。両方を並べ替えるにはO(n log n)が必要です。

注:私はEclipseコレクションのコミッターです

于 2012-09-06T15:44:35.003 に答える
3
String[] s1 = {"a","b","c"};
String[] s2 = {"b","c","a"} ;

Arrays.sort(s1);
Arrays.sort(s2);

    if(Arrays.equals(s1, s2)){
        System.out.println("ok");
}
于 2012-04-14T14:27:00.027 に答える
3

人間のやり方:

最初の配列を反復処理し、2番目の配列に各要素が存在するかどうかを確認してから、最初の配列の2番目の配列に対して同じことを行います。時間:n^2。このメソッドは、要素が繰り返されないことを前提としていることに注意してください。もしそうなら、チェックしている要素ごとに、最初に戻ってその要素のインスタンスの数を数えなければなりません(たとえばX)、そして成功はX番目の要素を見つけることとしてのみ数えます2番目の配列。これを行うと、2回目のチェックが不要になり、読者の練習問題として残されます(もしあなたがそんなに傾いているなら、それはそうです)。

boolean equal(String[] arr1, String[] arr2) {
    if(arr1.length != arr2.length) return false; // obviously
    main_loop:
    for(int i = 0; i < arr1.length; i++) {
        for(int j = 0; j < arr2.length; j++) {
            if(arr1[i].equals(arr2[j]))
                break main_loop;
        }
        return false;
    }
    main_loop:
    for(int i = 0; i < arr2.length; i++) {
        for(int j = 0; j < arr1.length; j++) {
            if(arr2[i].equals(arr1[j]))
                break main_loop;
        }
        return false;
    }
    // having got through both loops, we can now return true
}

より高度な方法:両方の配列を並べ替えて、両方を調べます。時間:n lg n

boolean equals(String[] arr1, String[] arr2) {
    if(arr1.length != arr2.length) return false;
    String[] copy1 = Arrays.copyOf(arr1,arr1.length); // java.util.Arrays
    String[] copy2 = Arrays.copyOf(arr2,arr2.length); // java.util.Arrays
    Arrays.sort(copy1);
    Arrays.sort(copy2);
    for(int i = 0; i < copy1.length; i++) {
        if(!copy1[i].equals(copy2[i])
            return false;
    }
    return true;
}

さらに高度な方法:ハッシュマップを使用して、最初の文字列配列のカウントを追加し、2番目の文字列配列のカウントを削除します。あなたがodneであるとき、すべてのカウントはゼロでなければなりません。

boolean equal(String[] arr1, String[] arr2) {
    if(arr1.length != arr2.length) return false;
    Map<String, Integer> map1 = new HashMap<String,Integer>();
    for(String str : arr1) {
        if(!map.containsKey(str)) {
            map.put(str, 1);
        } else {
            map.put(str, map.get(str) + 1); // add to count inthe map
        }
    }
    for(String str : arr1) {
        if(!map.containsKey(str)) {
            return false; // we have an element in arr2 not in arr1 - leave now
        } else {
            map.put(str, map.get(str) - 1); // remove to count inthe map
        }
    }
    for(Integer count : map.values()) {
        if(count.intValue() != 0) return false;
    }
    return true;
}
于 2012-04-14T14:35:52.290 に答える
3

Set::equals

注意:これは単純で邪魔にならないソリューションですが、入力配列/リストのいずれにも重複するエントリがないことが確実な場合(または重複を無視したい場合)にのみ機能します。

これには外部ライブラリは必要ありません。 順序に依存しない比較をSet<>行うメソッドがすでにあります。equals

public static <T> boolean areArraysEquivalent(T[] ary1, T[] ary2) {
    if (ary1 == null) {
        return ary2 == null;
    }

    if (ary2 == null) {
        return false;
    }

    List<T> list1 = Arrays.asList(ary1);
    List<T> list2 = Arrays.asList(ary2);
    return areListsEquivalent(list1, list2);
}


public static <T> boolean areListsEquivalent(List<T> list1, List<T> list2) {
    if (list1 == null) {
        return list2 == null;
    }

    if (list2 == null) {
        return false;
    }

    Set<T> set1 = new HashSet<>(list1);
    Set<T> set2 = new HashSet<>(list2);
    return set1.equals(set2);
}
于 2015-09-07T17:59:31.080 に答える
1

これは学校用だと思います。

考えられる戦略:

  • Arrays.sortを使用して両方の配列を並べ替えてから、ループを使用してs1[i]とs2[i]を比較します。
  • ループを使用し、s1の各アイテムについて、s2のアイテムを調べて同じものが含まれているかどうかを確認します
  • s1のアイテムをハッシュセットに入れてから、s2でループを使用して、アイテムがs1にあるかどうかを確認します。
于 2012-04-14T14:23:29.620 に答える
1

最初に2つの配列を並べ替えてから、行ごとに比較します...

public boolean areArraysEqual (String[] array1,String[] array2){    
    if (s1.length != s2.length){
        return false;
        }

    java.util.Arrays.sort(s1);
    java.util.Arrays.sort(s2);

    for (int i=0;i<s1.length;i++){
        if (! s1[i].equals(s2[i])){
            return false;
        }
    }

return true;
}
于 2012-04-15T11:03:39.647 に答える
0

内容を変更せずに配列を相互に比較したい場合は、不変の配列をカプセル化する型、そのソートされたバージョン、long一意であることが保証され、少なくともほとんどがオブジェクトと相関するシーケンスカウントを定義すると役立つ場合があります。年齢、および一致することがわかっている別の古いオブジェクトへの最初はnullの参照。すべての配列要素のハッシュ値を組み合わせたハッシュ値をキャッシュすることも役立つ場合があります。

このようなアプローチを使用すると、オブジェクトを他の何か(何か)と最初に比較するときに並べ替えが必要になりますが、その後は必要ありません。さらに、オブジェクトXとYが両方ともZと等しいことがわかった場合、XとYを比較すると、配列の内容を実際に調べることなく、それらが等しいと報告できます(ZがXとYよりも古い場合、両方が等しいと報告されます)同じ古いオブジェクトに対して。Xが最も若く、Yが最も古い場合、XはZに等しいことを認識し、ZはYに等しいことを認識します。次にXを何かと比較すると、既知の最も古いものが見つかります。に等しくなるのはYなので、もちろんYに等しくなります。

このようなアプローチでは、インターンと同様の同等性比較のパフォーマンス上の利点が得られますが、インターン辞書は必要ありません。

于 2013-11-23T00:08:58.047 に答える
0

小さなアレイの場合は、他の人が示唆しているように、を使用Arrays.sortします。より大きなアレイの場合は、よりもArrays.equals時間計算量が多い次のソリューションを使用できます。O(n)O(n log n)

public static boolean haveSameElements(Object[] arr1, Object[] arr2) {
    return arr1.length == arr2.length && counts(arr1).equals(counts(arr2));
}

// Map.merge and method references require Java 8
private static <T> Map<T, Integer> counts(T[] arr) {
    Map<T, Integer> map = new HashMap<>();
    for (T t : arr)
        map.merge(t, 1, Integer::sum);
    return map;
}
于 2015-11-13T02:05:20.720 に答える