Java:比较两个具有相同值的不同类型的对象,返回true

Java:比较两个具有相同值的不同类型的对象,返回true,java,object,compare,Java,Object,Compare,我有一些数据需要比较。我可能需要比较不同数据类型的值。以下是基本情况: Object a = (long) 1; Object b = (int) 1; System.out.println(Objects.equals(a, b)); //returns false Sysout.out.println(Objects.equals(a.toString(), b.toString())); //returns true 使用.toString()似乎是可行的解决方案吗?或者我应该走另

我有一些数据需要比较。我可能需要比较不同数据类型的值。以下是基本情况:

Object a = (long) 1;
Object b = (int) 1;


System.out.println(Objects.equals(a, b)); //returns false

Sysout.out.println(Objects.equals(a.toString(), b.toString())); //returns true
使用.toString()似乎是可行的解决方案吗?或者我应该走另一条路线

编辑:

此程序正在从配置单元表中读取数据,有些表中可能包含完全相同的数据,但数据类型不同。数据类型包括int、smallint、bigint、string、array、double、timestamp

我不关心数组比较,因为除了数组类型之外,没有其他东西可以容纳数组。但是,可以将字符串类型与时间戳进行比较。我也不关心int到double的比较,因为这会导致false

任何不带小数点的数值和不同的数据类型都应与其值进行比较,并且数据类型不匹配不应返回false

编辑:


任何带小数的数字在比较前都将四舍五入到小数点后3位。

只有当
toString()返回相同值但不同对象类型的相同表示时,才可以使用
toString

对于int和long,如果长时间停留在可以指定int的值的范围内,则可以

如果它是double和int,则由于小数点等原因,对于任何值子集都不合适

如果它们是相同的对象类型,
equals()
的实现应该足够了

根据您的用例,您可以根据遇到的字符串创建时间戳,以便与其他时间戳(如果有)进行比较,并相互比较INT

由于您需要将bigint表示为long,您也可以将smallint和int值转换为long,这样您就可以使用equals方法。

实际上,“不同类型,相同值”的概念是毫无意义的。当类型通过标准转换(加宽、缩小、[取消]装箱、字符串等)不相关时,根据定义,它们是不可比较的。他们有不同的话语领域。这就像是把每磅的体重和每磅的体重进行比较。没有语义关系

你可以施加任何语义关系来匹配你的可比性概念,但这需要你将你的“价值”纳入一个通用类型,并以标准的方式如果您认为“toString()”是您的答案,那么1’、(int)1、“1”和新的BigDecimal(new biginger(“1”)、2)可能会以不同的方式转换为“字符串”,这可能是您想要的,也可能不是您想要的

因此,如何呈现不兼容的类型完全取决于您。如果它们是不相容的,你就是那个扭曲规则的人,所以你必须规定如何扭曲规则。我强烈建议您仔细考虑您希望比较的领域,以及您计划如何处理不兼容的比较


当然,兼容的比较应该只使用内置机制。

如果您知道所有要比较的对象都是数字,那么可以将它们转换为java.math.BigDecimal实例并进行比较

Objects.equals(new BigDecimal(a.toString()), new BigDecimal(b.toString()));
如果a和b不为null,则equals(a,b)在内部调用a.equals(b)。
无论您将a声明为Obect,它实际上都是Long类型,因此根据Long的文档,a.equals(b)检查b是否是Long类型。这就是它返回false的原因。
使用toString()似乎不是比较数值对象的最佳方法

请尝试更好地使用诸如longValue()、intValue()等方法进行基元类型比较。

这里有一种方法,可以精确地进行编辑问题中描述的比较

/**
 * Compare objects for equal value, with some disregard for type.
 * <p>
 * The following types are considered similar, for the purpose of comparing values. The
 * values of the secondary types are converted to the first listed type for value comparison.
 * <ul>
 * <li>{@code long}, {@code int}, {@code short}</li>
 * <li>{@code double} <i>(rounded to 3 decimals before comparing)</i></li>
 * <li>{@code String}, {@code Timestamp}</li>
 * <li>Array <i>(elements are compared using this method, comparison is "deep")</i></li>
 * </ul>
 * Values for all other types are only considered equal if they have the exact same type
 * and {@code equals()} return {@code true}.
 * 
 * @param obj1 the first object to be compared.
 * @param obj2 the second object to be compared.
 * @return {@code true} only if the specified objects are equals according to the rules listed above.
 */
public static boolean equalValue(Object obj1, Object obj2) {
    // Compare null values
    if (obj1 == null)
        return (obj2 == null);
    if (obj2 == null)
        return false;

    Class<?> class1 = obj1.getClass();
    Class<?> class2 = obj2.getClass();

    // Compare double values, rounded to 3 decimal places
    if (class1 == Double.class && class2 == Double.class) {
        // Can't use Math.round() because it doesn't do round-half-up, and may overflow long value-range
        BigDecimal dec1 = BigDecimal.valueOf(((Number)obj1).doubleValue()).setScale(3, RoundingMode.HALF_UP);
        BigDecimal dec2 = BigDecimal.valueOf(((Number)obj2).doubleValue()).setScale(3, RoundingMode.HALF_UP);
        return dec1.equals(dec2); // equals() is ok, since we know they have same scale
    }

    // Compare arrays
    if (class1.isArray() && class2.isArray()) {
        int len = Array.getLength(obj1);
        if (len != Array.getLength(obj2))
            return false;
        for (int i = 0; i < len; i++)
            if (! equalValue(Array.get(obj1, i), Array.get(obj2, i)))
                return false;
        return true;
    }

    // Now that special cases are done, apply simple comparison for values of same type
    if (class1 == class2)
        return obj1.equals(obj2);

    // Compare long/int/short values
    if ((class1 == Long.class || class1 == Integer.class || class1 == Short.class) &&
        (class2 == Long.class || class2 == Integer.class || class2 == Short.class)) {
        return ((Number)obj1).longValue() == ((Number)obj2).longValue();
    }

    // Compare String/Timestamp values
    if ((class1 == String.class || obj1 instanceof Timestamp) &&
        (class2 == String.class || obj2 instanceof Timestamp)) {
        return obj1.toString().equals(obj2.toString());
    }

    return false; // Incomparable types
}
/**
*比较对象的值是否相等,而忽略类型。
*
*为了比较数值,以下类型被视为类似。这个
*次类型的值将转换为第一个列出的类型以进行值比较。
*
    *
  • {@code long},{@code int},{@code short}
  • *
  • {@code double}(比较前四舍五入到3位小数)
  • *
  • {@code String},{@code Timestamp}
  • *
  • 数组(使用此方法比较元素,比较“深入”)
  • *
*所有其他类型的值只有在具有完全相同的类型时才被视为相等 *和{@code equals()}返回{@code true}。 * *@param obj1是要比较的第一个对象。 *@param obj2要比较的第二个对象。 *@return{@code true}仅当指定的对象根据上面列出的规则相等时。 */ 公共静态布尔值相等(对象obj1、对象obj2){ //比较空值 如果(obj1==null) 返回值(obj2==null); 如果(obj2==null) 返回false; 类class1=obj1.getClass(); Class class2=obj2.getClass(); //比较双精度值,四舍五入到小数点后3位 if(class1==Double.class&&class2==Double.class){ //无法使用Math.round(),因为它不执行对半取整,并且可能会溢出长值范围 BigDecimal dec1=BigDecimal.valueOf((数字)obj1.doubleValue()).setScale(3,舍入模式。向上舍入); BigDecimal dec2=BigDecimal.valueOf((数字)obj2.doubleValue()).setScale(3,舍入模式。向上舍入); 返回dec1.equals(dec2);//equals()可以,因为我们知道它们具有相同的比例 } //比较数组 if(class1.isArray()&&class2.isArray()){ int len=Array.getLength(obj1); if(len!=Array.getLength(obj2)) 返回false; 对于(int i=0;i