是否有一种有效且快捷的方法来覆盖 TreeSet 中使用的 compareTo() 方法
Is there an efficient and quicker way to override compareTo() method used in TreeSet
我读取了包含六列的 table 并传递到 TreeSet
集合中。它确实工作正常,但是,我只是好奇是否有更有效的方法来覆盖 compareTo()
方法。提出这个问题的原因是我将有更多列的额外集合,而我这样做的方式在我看来效率低下且耗时。重要的是要注意我的所有 class 元素都是整数。
另外,我还有一个问题。 compareTo()
方法的其中一项工作是否像 HashCode()
在 HashMap()
中那样包含防止重复?
下面我展示了我如何定义 compareTo()
方法。
public int compareTo(Network o) {
int r = this.headNode > o.headNode? 1 : this.headNode < o.headNode ? -1 : 0;
if(r==0) { r = this.headPeriod1 > o.headPeriod1? 1 : this.headPeriod1 < o.headPeriod1? -1 : 0;
if(r==0) {
r = this.headPeriod2 > o.headPeriod2? 1 : this.headPeriod2 < o.headPeriod2? -1 : 0;
if(r==0) {
r = this.tailNode > o.tailNode? 1 : this.tailNode < o. tailNode? -1 : 0;
if(r==0) {
r = this.tailPeriod1 > o.tailPeriod1 ? 1 : this.tailPeriod1 < o.tailPeriod1 ? -1 : 0;
if(r==0) {
r = this.tailPeriod2 > o.tailPeriod2 ? 1 : this.tailPeriod2 < o.tailPeriod2 ? -1 : 0;
}
}
}
}
}
这样会有点shorter/simpler:
public int compareTo(Network o) {
int r = this.headNode - o.headNode;
if (r == 0) {
r = this.headPeriod1 - o.headPeriod1;
if (r == 0) {
r = this.headPeriod2 - o.headPeriod2;
if (r == 0) {
r = this.tailNode - o.tailNode;
if (r == 0) {
r = this.tailPeriod1 - o.tailPeriod1;
if (r == 0) {
r = this.tailPeriod2 - o.tailPeriod2;
}
}
}
}
}
您可以创建一个比较器以使其更具可读性:
public class Test {
int age;
int money;
int id;
public Test(int age, int money, int id) {
this.age = age;
this.money = money;
this.id = id;
}
public static void main(String... args) {
Test t1 = new Test(25,200,3);
Test t2 = new Test(30,50,5);
Test t3 = new Test(15,90,9);
Comparator<Test> comp = Comparator.<Test>comparingInt(x -> x.age)
.thenComparingInt(x -> x.money)
.thenComparingInt(x -> x.id);
Set<Test> set = new TreeSet<>(comp); // Pass the comparator to the Treeset, TreeMap, etc., or use it inside of you Comparable.compareTo method.
set.add(t1);
set.add(t2);
set.add(t3);
System.out.println(set); // [Test{age=15, money=90, id=9}, Test{age=25, money=200, id=3}, Test{age=30, money=50, id=5}]
}
@Override
public String toString() {
return "Test{" + "age=" + age + ", money=" + money + ", id=" + id + '}';
}
}
如你所见,你可以使用Comparator.comparingInt(x -> x.headNode)
.thenComparingInt(x -> x.headPeriod2)
.thenComparingInt(x -> x.tailNode)...
等等,让它更有意义。
随着 class 的增长,您可以继续添加更多 .thenComparingInt...。
这将按 headNode 对它们进行排序,然后按 headPeriod2,然后按 tailNode,依此类推。
(而不是 x,为该变量使用您想要的任何名称,例如(网络 -> network.headNode)
Comparator 中有更多的静态方法和实例方法来创建可以循环的不同 Comparator。
如果你实现了 Comparable 并且想在你的 compareTo 方法中使用你的 Comparator,那么将创建的 Comparator 作为实例字段并在 comparteTo 中使用比较器,如下所示:
public class Test implements Comparable<Test>{
int age;
int money;
int id;
Comparator<Test> comp = Comparator.<Test>comparingInt(x -> x.age)
.thenComparingInt(x -> x.money)
.thenComparingInt(x -> x.id);
public Test(int age, int money, int id) {
this.age = age;
this.money = money;
this.id = id;
}
public static void main(String... args) {
Test t1 = new Test(25,200,3);
Test t2 = new Test(30,50,5);
Test t3 = new Test(15,90,9);
Set<Test> set = new TreeSet<>();
set.add(t1);
set.add(t2);
set.add(t3);
System.out.println(set); // [Test{age=15, money=90, id=9}, Test{age=25, money=200, id=3}, Test{age=30, money=50, id=5}]
}
@Override
public String toString() {
return "Test{" + "age=" + age + ", money=" + money + ", id=" + id + '}';
}
@Override
public int compareTo(Test o) {
return comp.compare(this, o);
}
}
附方法参考:
public class Test implements Comparable<Test>{
private int age;
private int money;
private int id;
private final Comparator<Test> comp = Comparator.<Test>comparingInt(Test::getId)
.thenComparingInt(Test::getMoney)
.thenComparingInt(Test::getAge);
public static void main(String... args) {
Test t1 = new Test(25, 200, 3);
Test t2 = new Test(30, 50, 5);
Test t3 = new Test(15, 90, 9);
Set<Test> set = new TreeSet<>();
set.add(t1);
set.add(t2);
set.add(t3);
System.out.println(set); // [Test{age=25, money=200, id=3}, Test{age=30, money=50, id=5}, Test{age=15, money=90, id=9}]
}
public Test(int age, int money, int id) {
this.age = age;
this.money = money;
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public int compareTo(Test o) {
return comp.compare(this, o);
}
@Override
public String toString() {
return "Test{" + "age=" + age + ", money=" + money + ", id=" + id + '}';
}
}
希望对您有所帮助。
无论你怎么做,我都会强烈避免减去值来获得比较器的 < 或 > 结果。它会导致错误,是一个不好养成的习惯。查看以下内容:
int val1 = -1223222022;
int val2 = 2130200022;
int result = compareTo(val1, val2);
// This shows val1 > val2
if (result < 0) {
System.out.println(val1 + " < " + val2);
}
else if (result > 0) {
System.out.println(val1 + " > " + val2);
}
val1 = 1234450392;
val2 = -2022030049;
result = compareTo(val1, val2);
//this shows val2 < val2
if (result < 0) {
System.out.println(val1 + " < " + val2);
}
else if (result > 0) {
System.out.println(val1 + " > " + val2);
}
}
public static int compareTo(int a, int b) {
return a - b;
}
只需使用功能接口 Comparable 来整理您的需求。
我读取了包含六列的 table 并传递到 TreeSet
集合中。它确实工作正常,但是,我只是好奇是否有更有效的方法来覆盖 compareTo()
方法。提出这个问题的原因是我将有更多列的额外集合,而我这样做的方式在我看来效率低下且耗时。重要的是要注意我的所有 class 元素都是整数。
另外,我还有一个问题。 compareTo()
方法的其中一项工作是否像 HashCode()
在 HashMap()
中那样包含防止重复?
下面我展示了我如何定义 compareTo()
方法。
public int compareTo(Network o) {
int r = this.headNode > o.headNode? 1 : this.headNode < o.headNode ? -1 : 0;
if(r==0) { r = this.headPeriod1 > o.headPeriod1? 1 : this.headPeriod1 < o.headPeriod1? -1 : 0;
if(r==0) {
r = this.headPeriod2 > o.headPeriod2? 1 : this.headPeriod2 < o.headPeriod2? -1 : 0;
if(r==0) {
r = this.tailNode > o.tailNode? 1 : this.tailNode < o. tailNode? -1 : 0;
if(r==0) {
r = this.tailPeriod1 > o.tailPeriod1 ? 1 : this.tailPeriod1 < o.tailPeriod1 ? -1 : 0;
if(r==0) {
r = this.tailPeriod2 > o.tailPeriod2 ? 1 : this.tailPeriod2 < o.tailPeriod2 ? -1 : 0;
}
}
}
}
}
这样会有点shorter/simpler:
public int compareTo(Network o) {
int r = this.headNode - o.headNode;
if (r == 0) {
r = this.headPeriod1 - o.headPeriod1;
if (r == 0) {
r = this.headPeriod2 - o.headPeriod2;
if (r == 0) {
r = this.tailNode - o.tailNode;
if (r == 0) {
r = this.tailPeriod1 - o.tailPeriod1;
if (r == 0) {
r = this.tailPeriod2 - o.tailPeriod2;
}
}
}
}
}
您可以创建一个比较器以使其更具可读性:
public class Test {
int age;
int money;
int id;
public Test(int age, int money, int id) {
this.age = age;
this.money = money;
this.id = id;
}
public static void main(String... args) {
Test t1 = new Test(25,200,3);
Test t2 = new Test(30,50,5);
Test t3 = new Test(15,90,9);
Comparator<Test> comp = Comparator.<Test>comparingInt(x -> x.age)
.thenComparingInt(x -> x.money)
.thenComparingInt(x -> x.id);
Set<Test> set = new TreeSet<>(comp); // Pass the comparator to the Treeset, TreeMap, etc., or use it inside of you Comparable.compareTo method.
set.add(t1);
set.add(t2);
set.add(t3);
System.out.println(set); // [Test{age=15, money=90, id=9}, Test{age=25, money=200, id=3}, Test{age=30, money=50, id=5}]
}
@Override
public String toString() {
return "Test{" + "age=" + age + ", money=" + money + ", id=" + id + '}';
}
}
如你所见,你可以使用Comparator.comparingInt(x -> x.headNode) .thenComparingInt(x -> x.headPeriod2) .thenComparingInt(x -> x.tailNode)...
等等,让它更有意义。 随着 class 的增长,您可以继续添加更多 .thenComparingInt...。 这将按 headNode 对它们进行排序,然后按 headPeriod2,然后按 tailNode,依此类推。
(而不是 x,为该变量使用您想要的任何名称,例如(网络 -> network.headNode)
Comparator 中有更多的静态方法和实例方法来创建可以循环的不同 Comparator。
如果你实现了 Comparable 并且想在你的 compareTo 方法中使用你的 Comparator,那么将创建的 Comparator 作为实例字段并在 comparteTo 中使用比较器,如下所示:
public class Test implements Comparable<Test>{
int age;
int money;
int id;
Comparator<Test> comp = Comparator.<Test>comparingInt(x -> x.age)
.thenComparingInt(x -> x.money)
.thenComparingInt(x -> x.id);
public Test(int age, int money, int id) {
this.age = age;
this.money = money;
this.id = id;
}
public static void main(String... args) {
Test t1 = new Test(25,200,3);
Test t2 = new Test(30,50,5);
Test t3 = new Test(15,90,9);
Set<Test> set = new TreeSet<>();
set.add(t1);
set.add(t2);
set.add(t3);
System.out.println(set); // [Test{age=15, money=90, id=9}, Test{age=25, money=200, id=3}, Test{age=30, money=50, id=5}]
}
@Override
public String toString() {
return "Test{" + "age=" + age + ", money=" + money + ", id=" + id + '}';
}
@Override
public int compareTo(Test o) {
return comp.compare(this, o);
}
}
附方法参考:
public class Test implements Comparable<Test>{
private int age;
private int money;
private int id;
private final Comparator<Test> comp = Comparator.<Test>comparingInt(Test::getId)
.thenComparingInt(Test::getMoney)
.thenComparingInt(Test::getAge);
public static void main(String... args) {
Test t1 = new Test(25, 200, 3);
Test t2 = new Test(30, 50, 5);
Test t3 = new Test(15, 90, 9);
Set<Test> set = new TreeSet<>();
set.add(t1);
set.add(t2);
set.add(t3);
System.out.println(set); // [Test{age=25, money=200, id=3}, Test{age=30, money=50, id=5}, Test{age=15, money=90, id=9}]
}
public Test(int age, int money, int id) {
this.age = age;
this.money = money;
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public int compareTo(Test o) {
return comp.compare(this, o);
}
@Override
public String toString() {
return "Test{" + "age=" + age + ", money=" + money + ", id=" + id + '}';
}
}
希望对您有所帮助。
无论你怎么做,我都会强烈避免减去值来获得比较器的 < 或 > 结果。它会导致错误,是一个不好养成的习惯。查看以下内容:
int val1 = -1223222022;
int val2 = 2130200022;
int result = compareTo(val1, val2);
// This shows val1 > val2
if (result < 0) {
System.out.println(val1 + " < " + val2);
}
else if (result > 0) {
System.out.println(val1 + " > " + val2);
}
val1 = 1234450392;
val2 = -2022030049;
result = compareTo(val1, val2);
//this shows val2 < val2
if (result < 0) {
System.out.println(val1 + " < " + val2);
}
else if (result > 0) {
System.out.println(val1 + " > " + val2);
}
}
public static int compareTo(int a, int b) {
return a - b;
}
只需使用功能接口 Comparable 来整理您的需求。