以下は私の学生クラスです
class Student implements Comparable {
String name;
int rollNo;
@Override
public int compareTo(Object obj) {
return ((Student)obj).name.compareTo(this.name);
}
}
最新の変更:しかし、それでも正しい結果が得られない
@Override
public int compareTo(Object obj) {
Student s = (Student) obj;
if (name.equals(s.name)) { // achieving uniqueness
return 0;
} else {
if (rollNo < s.rollNo) {
return -1;
} else if (rollNo > s.rollNo) {
return 1;
} else {
// this makes `name` the second ordering option.
// names don't equal here
return name.compareTo(s.name);
}
}
}
TreeSet <Student>のオブジェクトを作成すると、一意の名前に基づいて、名前順に並べられたStudentオブジェクトのリストが表示されます。
ただし、TreeSet <Student>にstudent-rollNoで並べ替えた一意のstudent-nameが必要です。
コンパレータで可能ですか?誰かが私を助けることができます、すべての提案はありがたいです。ありがとう。
更新:ここに完全なプログラムがあります:
public class Student implements Comparable {
int rollNo;
String name;
Student(String n,int rno) {
rollNo=rno;
name=n;
}
/**
* @param args
*/
public static void main(String[] args) {
TreeSet<Student> ts = new TreeSet<Student>();
ts.add(new Student("bbb",2));
ts.add(new Student("aaa",4));
ts.add(new Student("bbb",2));
ts.add(new Student("ccc",3));
ts.add(new Student("aaa",1));
ts.add(new Student("bbb",2));
ts.add(new Student("bbb",5));
System.out.println(ts);
}
@Override
public int compareTo(Object obj) {
Student s = (Student) obj;
if (name.equals(s.name)) { // achieving uniqueness
return 0;
} else {
if (rollNo < s.rollNo) {
return -1;
} else if (rollNo > s.rollNo) {
return 1;
} else {
// this makes `name` the second ordering option.
// names don't equal here
return name.compareTo(s.name);
}
}
}
@Override
public String toString() {
return name + rollNo;
}
}
更新:2:ご提案ありがとうございます。まだまだ必要です:)
/*
* Actual scenario is having different properties,
* So here I am just relating my actual scenario with Student class
*/
class Student implements Comparable {
// sorting required on rollNo
int rollNo;
// Unique name is required
String name;
Student(String n, int rno) {
rollNo = rno;
name = n;
}
/**
*
* @param args
*/
public static void main(String[] args) {
TreeSet<Student> tsName = new TreeSet<Student>();
// here by default, order & uniqueness by name only
tsName.add(new Student("ccc", 2));
tsName.add(new Student("aaa", 4));
tsName.add(new Student("ddd", 1));
tsName.add(new Student("bbb", 3));
tsName.add(new Student("ddd", 5));
// output: aaa:4, bbb:3, ccc:2, ddd:1
System.out.println(tsName);
// creating new comparator for student RollNo
TreeSet<Student> tsRollNo = new TreeSet<Student>(new Comparator<Student>() {
public int compare(Student stud1, Student stud2) {
return new Integer(stud1.rollNo).compareTo(stud2.rollNo);
}
});
tsRollNo.addAll(tsName);
System.out.println(tsRollNo);
// now got the desire output: ddd:1, ccc:2, bbb:3, aaa:4
}
public boolean equals(Object obj) {
// internally not used to check equality while adding objects
// in TreeSet
System.out.println("equals() for " + this + " & " + ((Student) obj));
return false;// return false/true doesn't make any sense here
}
@Override
public int compareTo(Object obj) {
Student s = (Student) obj;
// internally inside TreeSet, compareTo is used to decide
// whether two objects are equal or not,
// i.e. compareTo will return 0 for same object(here student name)
System.out.println("compareTo() for " + this + " & " + ((Student) obj));
// achieving uniqueness
return name.compareTo(s.name);
}
@Override
public String toString() {
return name + ":" + rollNo;
}
}
[〜#〜] output [〜#〜]:
compareTo() for aaa:4 & ccc:2
compareTo() for ddd:1 & ccc:2
compareTo() for bbb:3 & ccc:2
compareTo() for bbb:3 & aaa:4
compareTo() for ddd:5 & ccc:2
compareTo() for ddd:5 & ddd:1
[aaa:4, bbb:3, ccc:2, ddd:1]
[ddd:1, ccc:2, bbb:3, aaa:4]
友達、2つのコンパレータを使って得たものは何でも、オブジェクトを追加しながら同じことを達成することは可能ですか?最初に要素を追加してから、新しいコンパレータを使用して目的の順序を実現することはできません。
私は何千もの値を操作しているので、パフォーマンスも考慮する必要があります。
in TreeSet
ソートと一意のチェックのための要素を追加しながら、コンパレータを使用します。
ここで問題となるのは、ロール番号にコンパレータを使用すると、ロール番号と一意のロール番号でソートされることです。ツリーセットで両方を一緒にすることはできません。
私はあなたが行くことをお勧めします。
TreeSet
ここでは、重複の削除に集中しますArrayList
に移動し、任意の順序で並べ替えます@ ralphによる回答 指定されたコンパレータでTreeSet
を使用することは良いことです、それを使用してください。
生のコレクションを使用するだけでなく、正しい動作を公開して文書化するクラス内に「学生データベース」の概念をラップする必要があります。特定の順序で学生のリストを取得することが設計要件である場合は、メソッドを公開します(おそらく、それを示す_Iterable<Student>
_を返します。舞台裏では、使用パターンに応じてさまざまなことを実行できます。
Set
sまたはMaps
を維持し、関心のある分野で学生を並べ替え/索引付けします。Arrays.sort()
と指定されたComparator
を使用したオンデマンドのインプレース配列ソート。例...
_final class StudentTable {
private static final Comparator<Student> studentRollNoComparator = ...;
private final SortedSet<Student> sortedByRollNo =
new TreeSet<Student>(studentRollNoComparator);
public Iterable<Student> studentsOrderedByRollNo()
{
return sortedByRollNo;
}
//see below
public void addStudent(final Student foo) { ... }
}
_
学生名のみを比較するには、Student
クラスのequals()
とhashCode()
をオーバーライドする必要があります。次に、TreeSet
に(サイレントに)一意性を取得します。明らかに、これを行う場合は、newStudent
を挿入する前にstudentSet.contains(newStudent)
かどうかを確認するために防御的にコーディングする必要があるため、重複があるかどうかがわかります。
_final class Student implements Comparable {
...
@Override
public boolean equals(Object o)
{
return o!=null &&
o (instanceof Student) &&
((Student)o).name.equals(this.name);
}
@Override
public int hashCode()
{
return name.hashCode(); // good enough for this purpose
}
}
_
これを設定すると、学生を挿入するコードは次のようになります。
_void addNewStudent(final Student toAdd)
{
if (studentSet.contains(toAdd)) {
throw new IllegalStateException("Student with same name as "+toAdd+" already exists.");
}
studentSet.add(toAdd);
}
_
その場合、ツリーセットは名前が一意の学生でいっぱいになり、そうでない場合は追加操作で失敗が報告されます。 (例外をスローすることは、1つの潜在的なルートにすぎず、重複した名前の学生を追加することが実際には例外的な条件である場合にのみ適切ですが、あなたは言いませんでした。)
別のコンパレータを使用して新しいTreeSetを初期化できます。 -つまり、新しいコンパレータを作成し(Java.util.Comparatorインターフェイスを実装)、このコンパレータを使用して新しいTreeSetを初期化し、すべての学生をセットに追加するだけです。
TreeSet<Student> sortedByRollNo new TreeSet<Student>(new RollNoComparator());
sortedByRollNo.addAll(allStudents);
TreeSet<Student> sortedByY new TreeSet<Student>(new YComparator());
sortedByY.addAll(allStudents);
各ツリーセットは、ソート用に独自のコンパレータを持つことができます。コンパレータが指定されていない場合、ツリーセットはセット要素の自然順序を使用します。
追加
Uniqe Studentという名前だけが必要な場合は、次の2つの方法があります。
このようなビット:
TreeSet<Student> sortedByRollNo new TreeSet<Student>(new RollNoComparator());
sortedByRollNo.addAll(new TreeSet<Student>(allStudends)); //this uses the native comparator to filter by uniqe name
ここで遅れて申し訳ありませんが、ここにエレガントな解決策があります:
public class OwnSortedList<T> extends TreeSet<T> {
private static final long serialVersionUID = 7109828721678745520L;
public OwnSortedList(Comparator<T> levelScoreComparator) {
super(levelScoreComparator);
}
public boolean add(T e) {
boolean existsElement = false;
Iterator<T> it = iterator();
while(it.hasNext() && !existsElement){
T nextElement = it.next();
if(nextElement.equals(e)){
// Element found
existsElement = true;
Comparator<? super T> comparator = comparator();
int compare = comparator.compare(nextElement, e);
if(compare > 0){
remove(nextElement);
super.add(e);
//element added so return true
return true;
}
}
}
if(!existsElement){
super.add(e);
}
return false;
}
}