我不确定如何在我的复杂类中实现类似的接口。我有以下示例代码,我正在尝试并试图解决它。我知道它应该像public double compareTo (Complex o)
这样的东西,但我不太确定如何做到这一点。关于我将如何实施它的任何建议?:
import java.util.Scanner;
public class Complex implements Cloneable, Comparable {
private double real;
private double imag;
/*
* public Object clone() throws CloneNotSupportedException { Complex
* objClone = new Complex(); objClone.setReal(this.real);
* objClone.setImag(this.imag); return objClone; }
*/
public Complex(double real, double imag) {
this.real = real;
this.imag = imag;
}
public Complex(double real) {
this.real = real;
}
public Complex() {
}
public void setReal(double real) {
this.real = real;
}
public void setImag(double imag) {
this.imag = imag;
}
public double getReal() {
return real;
}
public double getImag() {
return imag;
}
public void add(Complex num1, Complex num2) {
this.real = num1.real + num2.real;
this.imag = num1.imag + num2.imag;
}
public Complex subtract(Complex num) {
Complex a = this;
double real = a.real - num.real;
double imag = a.imag - num.imag;
return new Complex(real, imag);
}
public Complex multiply(Complex num) {
Complex a = this;
double real = a.real * num.real - a.imag * num.imag;
double imag = a.real * num.imag + a.imag * num.real;
return new Complex(real, imag);
}
public Complex divide(Complex c1, Complex c2) {
return new Complex((c1.real * c2.real + c1.imag * c2.imag) / (c2.real * c2.real + c2.imag * c2.imag),
(c1.imag * c2.real - c1.real * c2.imag) / (c2.real * c2.real + c2.imag * c2.imag));
}
public double absolute() {
return Math.sqrt(real * real + imag * imag);
}
public String toString() {
return this.real + " + " + this.imag + "i";
}
@Override
public Complex clone() throws CloneNotSupportedException {
super.clone();
return new Complex(real, imag);
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.print("Enter the first set of complex numbers respectively: ");
double a = in.nextDouble();
double b = in.nextDouble();
Complex c1 = new Complex(a, b);
System.out.print("Enter the second set of complex numbers respectively: ");
double c = in.nextDouble();
double d = in.nextDouble();
Complex c2 = new Complex(c, d);
Complex result = new Complex(c, d);
result.add(c1, c2);
System.out.println("(" + a + " + " + b + "i) + (" + c + " + " + d + "i) = " + result.toString());
System.out.println("(" + a + " + " + b + "i) - (" + c + " + " + d + "i) = " + c1.subtract(c2));
System.out.println("(" + a + " + " + b + "i) * (" + c + " + " + d + "i) = " + c1.multiply(c2));
System.out.println("(" + a + " + " + b + "i) / (" + c + " + " + d + "i) = " + result.divide(c1, c2).toString());
System.out.println("|" + a + " + " + b + "i| = " + c1.absolute());
}
public double compareTo(Complex other) {
return this.getReal() - other.getReal();
}
}
答案 0 :(得分:2)
首先,compareTo
接口的Comparator
方法返回int
,而不是double
。其次,如果要比较Comparator中的两个double值,则不应使用a - b
模式。相反,请使用预定义的Double.compare
方法:
public int compareTo(Complex other) {
return Double.compare(this.getReal(), other.getReal());
}
此方法会仔细处理所有特殊值,例如-0.0
或NaN
,这些值不易手动处理。请注意,其他类型也存在类似的方法:Integer.compare
,Long.compare
等。它最好使用它们。
当然应该注意的是,对于复数而言,没有自然顺序。在这里,您只需比较实际部分,完全忽略虚部。
答案 1 :(得分:2)
从数学的角度来看,复数不能被排序,因此不适合Comparable
接口。引用the wikipedia article:
因为复数自然被认为存在于二维平面上,所以复数的集合没有自然的线性排序。
复数上没有与加法和乘法兼容的线性排序。在形式上,我们说复数不能具有有序字段的结构。这是因为有序字段中的任何平方至少为0,但是i 2 = -1。
话虽如此,从技术上讲,没有什么可以阻止你实现这个界面。例如,您可以决定首先按实际部分排序,然后按虚部分排序。请注意,compareTo
方法的合同要求您返回int
,而不是double
。此外,您应该将类定义为扩展Comparable<Complex>
而不是原始Comparable
,因此您不必使用转换和运行时类型检查:
@Override
public int compareTo(Complex other) {
int realCompare = Double.compare(getReal(), other.getReal());
if (realCompare != 0) {
return realCompare;
}
return = Double.compare(getImag(), other.getImag());
}
修改:
强>
JDK 8的Comparator
接口的改进允许使用相同的行为实现更优雅的实现:
public int compareTo(Complex other) {
return Comparator.comparingDouble(Complex::getReal)
.thenComparingDouble(Complex::getImag)
.compare(this, other);
}
答案 2 :(得分:1)
值得注意的几点。
正如其他答案所指出的那样,如果该类的实例具有自然排序,则通常应该只实现Comparable
。由于复杂数字没有自然排序,因此您可能不应该实现Comparable
。
如果您要提供自然顺序,那么您应该实现Comparable<Complex>
来表示与Complex
的其他实例进行比较(而不是与其他对象进行比较)。
实施Comparable
的更好选择是为您的班级提供一个或多个Comparator
个对象,可用于提供任意数量的订单。例如:
public class Complex {
private double real;
private double imaginary;
public static final Comparator<Complex> COMPARE_BY_REAL =
Comparator.comparingDouble(Complex::getReal);
public static final Comparator<Complex> COMPARE_BY_IMAGINARY =
Comparator.comparingDouble(Complex::getImaginary);
public static final Comparator<Complex> COMPARE_BY_MODULUS =
Comparator.comparingDouble(Complex::getModulus);
private double getModulus() {
return Math.sqrt(real * real + imaginary * imaginary);
}
}
然后该类的用户可以选择对使用有意义的排序:
Optional<Complex> closestToOrigin = complexList.stream().min(Complex::COMPARE_BY_MODULUS);