10

クラスがあります

public class StudentVO {
   int age;
   String name;  
}

2 つの異なる分野で同じクラスを使用しました。ある場所では、年齢に基づいて並べ替える必要があります。別の場所では、名前に基づいて並べ替える必要があり、別の場所では、年齢と名前の両方に基づいて並べ替える必要がある場合があります。これどうやってするの?1 つのフィールドの場合、オーバーライドできますcompareTo()

これを行うことは可能ですか?

4

7 に答える 7

18

1)年齢と名前でソートするための 2 つのComparatorを別々に記述してから、 Collections.sort(List,Comparator)を使用する必要があります。このようなもの:

class StudentVO {
  private String name;
  private int age;
  public String getName() {
      return name;
  }
  public void setName(String name) {
      this.name = name;
  }
  public int getAge() {
      return age;
  }
  public void setAge(int age) {
      this.age = age;
  }
}

class AgeComparator implements Comparator<StudentVO> {

@Override
public int compare(StudentVO o1, StudentVO o2) {
    Integer age1 = o1.getAge();
    Integer age2 = o2.getAge();
    return age1.compareTo(age2);
  }

}

class NameComparator implements Comparator<StudentVO> {

  @Override
  public int compare(StudentVO o1, StudentVO o2) {
      return o1.getName().compareTo(o2.getName());
  }

}

そして、それらを使用して、に基づいてソートするにはage:

Collections.sort(list,new AgeComparator());

に基づいてソートするにはname:

Collections.sort(list,new NameComparator());

2)の にソートの自然な順序があると思われる場合は、 sort by としListます。次に、Comparable forおよびfor を使用します。StudentVOageageComparatorname

 class StudentVO implements Comparable<StudentVO>{
    private String name;
    private int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public int compareTo(StudentVO o) {
        return ((Integer)getAge()).compareTo(o.getAge());
    }
}

class NameComparator implements Comparator<StudentVO> {

    @Override
    public int compare(StudentVO o1, StudentVO o2) {
        return o1.getName().compareTo(o2.getName());
    }

 }

そして、それらを使用して、に基づいてソートするにはage:

Collections.sort(list);

に基づいてソートするにはname:

Collections.sort(list,new NameComparator());
于 2013-04-25T04:54:15.023 に答える
2

私も最近、この問題を解決しなければなりませんでした。これがあなたのシナリオとまったく同じかどうかはわかりませんが、問題の範囲が非常に限られていたため、グリッドの 0 個以上の列のメモリ内並べ替え、OOM 条件のハンドウェーブなどを作成する必要がありました。

各列のコンパレータと、コンパレータのリストを取るコンパレータを作成しました。どの列をどの順序で並べ替える必要があるかを特定したので、対応するコンパレータのインスタンスをコンパレータのリストに追加しました。次に、連鎖コンパレーターを使用して、実際のソートを実行します。

public class MyObject
{
    private String name;
    private int age;
    private Date registered;
}

したがって、各コンパレーターは次のようになります。

public class NameComparator
    implements Comparator<MyObject>
{
    public int compare(MyObject o1, MyObject o2)
    {
        return o1.getName().compareTo(o2.getName);
    }
}

連鎖コンパレータの場合:

public class ChainedComparator
    implements Comparator<MyObject>
{
    public int compare(MyObject o1, MyObject o2) {
        for(Comparator<MyObject> comparator : comparators) {
            int result = comparator.compare(o1,o2);
            if(result != 0) {
                return result;
            }
        }
        return 0;
    }
}
    private List<Comparator<MyObject>> comparators = new ArrayList<>();
}

あなたの想像力に任せて、並べ替えを解析し、連鎖したコンパレータを構築します。必要に応じて連鎖コンパレータのサブコンパレータへの呼び出しでパラメータの順序を交換することによって実装した方向も組み込んだため、実際にはこれをもう少し複雑にしました。

于 2014-09-30T19:21:35.650 に答える
1

Java では、オブジェクトを比較する主な方法が 2 つあります。1 つ目は、クラス自体がComparableインターフェースを実装することです。これは、1 つの実装のみを意味します。2 つ目は、クラスにComparatorインターフェイスを実装させることです。このようにして、同じクラスに対して複数のコンパレーターを使用できます。

これは、たとえば、StudentVo クラスで 3 つの異なるコンパレータを定義できることを意味します。1 つは名前のみを比較し、もう 1 つは年齢を比較し、最後の 1 つは両方のプロパティを比較します。

アプリケーションでは、比較対象に基づいて、必要に応じた実装を使用します。1 つの場所で、学生の年齢を Collections.sort(myStudents , new CompareStudentOnAge()) で比較します。別の場所では、別の実装を使用します。

このブログ投稿でいくつかの説明を見つけることができます: http://javarevisited.blogspot.fr/2011/06/comparator-and-comparable-in-java.html

于 2013-04-25T05:12:57.840 に答える