0

RankedObject実装するクラスを書くときComparable<RankedObject>

public static class RankedObj implements Comparable<RankedObj>      {
    int i;
    public RankedObj(int i)     {
        this.i=i;
    }

    @Override
    public String toString() {
        return "RankedObj [i=" + i + "]";
    }


    @Override
    public int compareTo(RankedObj o) {
        if(this.i == 3)     {  // '3' will always be the smallest item
            return -1;
    }
    return this.i-o.i;
}

RankedObjectのリストを「全体的に昇順で、同時に数字3が常にsmallest一つになるように」したい。テスト中に、元のリストの順序が実際に結果に影響し、場合によっては結果が正しくないことがわかりました。すなわち:

//----CASE 1----
List<RankedObj> list = new ArrayList<>();
list.add(new RankedObj(11));
list.add(new RankedObj(1));
list.add(new RankedObj(12));
list.add(new RankedObj(3));
list.add(new RankedObj(8));
Collections.sort(list);
System.out.println(list);

//output (as I intend)
[RankedObj [i=3], RankedObj [i=1], RankedObj [i=8], RankedObj [i=11], RankedObj [i=12]]

//----CASE 2----
List<RankedObj> list = new ArrayList<>();
list.add(new RankedObj(11));
list.add(new RankedObj(12));
list.add(new RankedObj(3));
list.add(new RankedObj(8));
list.add(new RankedObj(1));
Collections.sort(list);
System.out.println(list);

//output (not what my Comparable intends)
[RankedObj [i=1], RankedObj [i=3], RankedObj [i=8], RankedObj [i=11], RankedObj [i=12]]

誰かが私の理由を教えてもらえますか? また、「3」が最小の項目でありながら、全体的に昇順でリストを作成する目的をどのように実現できますか? どうもありがとう!

PSComparatorコードが のコードと同じであるを使用した私のテストによるとComparable、結果は同じです。

Collections.sort(list, new Comparator<RankedObj>() {
    @Override
    public int compare(RankedObj o1, RankedObj o2) {
        if(o1.i == 3)       {
            return -1;
    }
    return o1.i-o2.i;
    }
});
4

2 に答える 2

3

あなたの比較は対称的ではありません。

次の 2 つの呼び出しを検討してください。

RankedObj x = new RankedObj(1);
RankedObj y = new RankedObj(3);
System.out.println(x.compareTo(y)); // -2
System.out.println(y.compareTo(x)); // -1

どちらも 0 の答えを返すか、反対の符号の答えを返す必要があります。代わりに、どちらも負の値を返します - 最初の呼び出しでo1.iは 1 (3 ではない) であるため、フォールバックしますo1.i - o2.i- これはまだ負です。

さらに、非常に強い負の値がある場合、そこから強い正の値を減算すると、減算がオーバーフローするという問題があります。

対称になるように修正し、オーバーフローを回避する必要があります。これはそれを行う必要があります:

@Override
public int compareTo(RankedObj o) {
    // Handle equality first
    if (this.i == o.i) {
        return 0;
    }
    // Handle the magic value correctly on *both* sides
    if(this.i == 3) {
        return -1;
    }
    if (o.i == 3) {
        return 1;
    }
    // Fall back to normal comparsions
    return Integer.compare(i, o.i);
}
于 2013-04-16T13:23:01.827 に答える
2

試す:

@Override
public int compare(RankedObj o1, RankedObj o2) {
    if(o1.i == o2.i){       {
        return 0;
    } else if(o1.i == 3)       {
        return -1;
    } else if (o2.i == 3){
        return 1;
    }
return o1.i-o2.i;
}

実装では、一方の値から他方の値を減算するときにオーバーフローが発生しない小さな数値のみを使用していると想定しています。

于 2013-04-16T13:24:06.630 に答える