java - 从语义上比较不同类型的数字

问题描述 投票:0回答:4

假设我有三个数字:

Comparable n1 = new Integer(432);
Comparable n2 = new Long(40);
Comparable n3 = new Double(500.12);

我想通过

Comparable
界面比较这些数字。然而,这会导致
ClassCastException

n1.compareTo(n2);

有没有办法(实用函数、外部库……)来比较不同类型的数字?在上面的示例中,从语义上看,数字

n2
小于
n1
,并且
n1
小于
n3

在代码中,我不知道数字的具体类型。因此,我依赖

Comparable
界面。

java numbers comparison comparator comparable
4个回答
1
投票

第一个答案完全正确地说明了为什么会出现 ClassCastException - Comparable 接口是通用的,只能用于相同具体类型的对象。

可能还有其他方法可以解决您的问题:

原语及其对象包装器

如果您确定所有数字都是基元 (

int, long, float, double

) 或表示基元的类的对象 (
Integer, Long, Float, Double
),那么您可以只使用普通的比较运算符,例如相当于 
n1.compareTo(n2);


int b = n1 > n2 ? 1 : (n1 < n2 ? -1 : 0);

Number
的子类

如果您确定所有变量都是扩展

Number

 的类,即 
AtomicInteger, AtomicLong, BigDecimal, BigInteger, Byte, Double, Float, Integer, Long, Short
,您可以使用以下内容:

private int compareNumbers(Number n1, Number n2) { Double n2c = n2.doubleValue(); Double n1c = n1.doubleValue(); return n1c.compareTo(n2c); } public static void main (String[] args) { Integer n1 = new Integer(432); Long n2 = new Long(40); Double n3 = new Double(500.12); System.out.println(compareNumbers(n1,n2)); }

编辑

为了回应与OP的评论讨论 - 我们注意到,如果比较两个超出

Double

范围的
Number
BigDecimal
数字,使用
BigInteger
作为
Double
比较的基类可能会给出虚假的相等性(因此 
.doubleValue()
 根据需要返回 
Double.POSITIVE_INFINITY
Double.NEGATIVE_INFINITY

如果这是一个问题,

compareNumbers()

可以更改如下:

private int compareNumbers(Number n1, Number n2) { BigDecimal n2c = new BigDecimal(n2.toString()); BigDecimal n1c = new BigDecimal(n1.toString()); return n1c.compareTo(n2c); }

/编辑

实施

Comparable
 但不扩展 
Number


如果您甚至不能确定您的变量扩展了 Number,并且您可能正在使用表示数字的类来处理变量,实现 Comparable,但不扩展 Number,我相信您只能比较参数,如果它们是同一个班级的。在这种情况下,这应该可行,但我无法真正想象用例:

Comparable n1 = new WierdNonNumberExtendingInteger(432); Comparable n2 = new WierdNonNumberExtendingLong(40); Comparable n3 = new WierdNonNumberExtendingDouble(500.12); Integer b = null; if (n1.getClass().isInstance(n2)) { b = n1.compareTo(n2); } else { System.err.println("Can't compare apples and oranges"); System.err.print("You tried to compare " + n1.getClass().getSimpleName()); System.err.print(" with " + n2.getClass().getSimpleName()); } System.out.println(b);
    

0
投票
你不能这样比较它们。 Comparable 是一个通用接口,它只接受相同的类型。

可以使用转换方法:

Comparable<Double> n1 = convertNumber(new Integer(432)); Comparable<Double> n2 = convertNumber(new Long(40)); Comparable<Double> n3 = convertNumber(new Double(500.12)); System.out.println(n1.compareTo(n2)); ... public Double convertNumber(Object o) { if(o instanceof Double) { return (Double)o; } else if(o instanceof Long) { return ((Long)o).doubleValue(); } else if(o instanceof Integer) { return ((Integer)o).doubleValue(); } return null; }
    

0
投票
正如人们提到的,您不能“按原样”比较它们,但您可以实现一个新的比较器,该比较器将接收不同的可能值并知道如何处理它们。下面是一个可能的实现,其中您有不同的构造函数(每个可能的值 - 可能可以改进该部分),它将给定值转换为“基本”类型(在我的例子中为双精度) - 并且compareTo方法可以处理所有支持的类型由不同的构造函数。

public class MyTestClass
{
    public static void main (String[] args) throws java.lang.Exception
    {
        MyComparator n1 = new MyComparator(new Integer(432));
        MyComparator n2 = new MyComparator(new Long(40));
        MyComparator n3 = new MyComparator(new Double(500.12));
    }

static class MyComparator implements Comparable
{
    double baseVal = 0.0d;

    public double getValue() {
        return baseVal;
    }

    public MyComparator(double d) {
        this.baseVal = d;
    }

    public MyComparator(Long l) {
        this.baseVal = l.doubleValue();
    }

    public MyComparator(int i) {
        this.baseVal = (double)i;
    }

    public int compareTo(MyComparator toCompare) {
        return ((Double)this.getValue()).compareTo(toCompare.getValue());
    }

    public int compareTo(Object o) {
        // implemented only to support required interface methods
        return 0;
    }
}
}

public class MyTestClass { public static void main (String[] args) throws java.lang.Exception { MyComparator n1 = new MyComparator(new Integer(432)); MyComparator n2 = new MyComparator(new Long(40)); MyComparator n3 = new MyComparator(new Double(500.12)); } static class MyComparator implements Comparable { double baseVal = 0.0d; public double getValue() { return baseVal; } public MyComparator(double d) { this.baseVal = d; } public MyComparator(Long l) { this.baseVal = l.doubleValue(); } public MyComparator(int i) { this.baseVal = (double)i; } public int compareTo(MyComparator toCompare) { return ((Double)this.getValue()).compareTo(toCompare.getValue()); } public int compareTo(Object o) { // implemented only to support required interface methods return 0; } } }


    


0
投票
您始终可以在 Number 的子类(Integer,Float,...)上调用 intValue() 方法,这是比较不同类型的方法:

    
© www.soinside.com 2019 - 2024. All rights reserved.