java 两个数比较_java-比较两个通用数字的值

java-比较两个通用数字的值

我想与两个类型均为TreeSet的变量进行比较。现在,我想知道两个变量中的哪个大于另一个或相等。 不幸的是,我还不知道确切的类型,我只知道它将是Number的子类型。我该怎么做?

编辑:我尝试了使用TreeSets的另一种解决方法,该方法实际上可以自然排序(当然可以,除AtomicInteger和AtomicLong外,Number的所有子类都实现了Comparable)。 因此,我将丢失重复的值。 使用Lists时,由于绑定不匹配,因此Collection.sort()将不接受我的列表。 非常不满意。

12个解决方案

31 votes

这应该适用于所有扩展Number并与其可比较的类。 与Sarmun答案相比,通过添加&Comparable,您可以删除所有类型检查,并免费提供运行时类型检查和错误抛出。

class NumberComparator implements Comparator {

public int compare( T a, T b ) throws ClassCastException {

return a.compareTo( b );

}

}

BennyBoy answered 2019-12-31T20:55:18Z

30 votes

一个有效的(但脆弱的)解决方案是这样的:

class NumberComparator implements Comparator {

public int compare(Number a, Number b){

return new BigDecimal(a.toString()).compareTo(new BigDecimal(b.toString()));

}

}

但是,它仍然不是很好,因为它依靠NaN返回可以由false解析的值(标准Java Number类可以执行,但是Number合同不需要)。

七年后编辑:正如评论中所指出的,您可以考虑(至少?)三种特殊情况NaN:

NaN,它大于所有值,除了相等的自身

NaN,它等于所有事物,除了等于它的自身

NaN,这比较麻烦/不可能进行比较,因为与NaN进行的所有比较都会导致false,包括检查自身是否相等。

gustafc answered 2019-12-31T20:54:57Z

14 votes

一种可能适合您的解决方案是不与T extends Number一起使用,而与T extends Number & Comparable一起使用。这种类型的意思是:“ T只能设置为实现两个接口的类型。”

这样您就可以编写适用于所有可比较数字的代码。 静态打字且优雅。

这与BennyBoy提出的解决方案相同,但是它适用于各种方法,不仅适用于比较器类。

public static > void compfunc(T n1, T n2) {

if (n1.compareTo(n2) > 0) System.out.println("n1 is bigger");

}

public void test() {

compfunc(2, 1); // Works with Integer.

compfunc(2.0, 1.0); // And all other types that are subtypes of both Number and Comparable.

compfunc(2, 1.0); // Compilation error! Different types.

compfunc(new AtomicInteger(1), new AtomicInteger(2)); // Compilation error! Not subtype of Comparable

}

Lii answered 2019-12-31T20:55:47Z

12 votes

问了类似的问题并在这里研究了答案之后,我想到了以下内容。 我认为它比gustafc提供的解决方案更有效,更强大:

public int compare(Number x, Number y) {

if(isSpecial(x) || isSpecial(y))

return Double.compare(x.doubleValue(), y.doubleValue());

else

return toBigDecimal(x).compareTo(toBigDecimal(y));

}

private static boolean isSpecial(Number x) {

boolean specialDouble = x instanceof Double

&& (Double.isNaN((Double) x) || Double.isInfinite((Double) x));

boolean specialFloat = x instanceof Float

&& (Float.isNaN((Float) x) || Float.isInfinite((Float) x));

return specialDouble || specialFloat;

}

private static BigDecimal toBigDecimal(Number number) {

if(number instanceof BigDecimal)

return (BigDecimal) number;

if(number instanceof BigInteger)

return new BigDecimal((BigInteger) number);

if(number instanceof Byte || number instanceof Short

|| number instanceof Integer || number instanceof Long)

return new BigDecimal(number.longValue());

if(number instanceof Float || number instanceof Double)

return new BigDecimal(number.doubleValue());

try {

return new BigDecimal(number.toString());

} catch(final NumberFormatException e) {

throw new RuntimeException("The given number (\"" + number + "\" of class " + number.getClass().getName() + ") does not have a parsable string representation", e);

}

}

rolve answered 2019-12-31T20:56:07Z

5 votes

最“通用”的Java原语数字是double,因此只需使用

a.doubleValue() > b.doubleValue()

在大多数情况下应该足够了,但是...将数字转换为双精度时,这里存在一些细微问题。 例如,BigInteger可以实现以下功能:

BigInteger a = new BigInteger("9999999999999992");

BigInteger b = new BigInteger("9999999999999991");

System.out.println(a.doubleValue() > b.doubleValue());

System.out.println(a.doubleValue() == b.doubleValue());

结果是:

false

true

尽管我希望这是非常极端的情况,但这是可能的。 而且-没有通用的100%准确方法。 数字接口没有像extraValue()这样的方法可以转换为某种能够以完美的方式表示数字而不丢失任何信息的类型。

实际上,实际上不可能有这样的完美数字-例如,使用有限空间的任何算术运算都无法表示数字Pi。

kopper answered 2019-12-31T20:56:45Z

2 votes

这应该适用于所有扩展Number并与其可比较的类。

class NumberComparator implements Comparator {

public int compare(T a, T b){

if (a instanceof Comparable)

if (a.getClass().equals(b.getClass()))

return ((Comparable)a).compareTo(b);

throw new UnsupportedOperationException();

}

}

Sarmun answered 2019-12-31T20:57:05Z

2 votes

if(yourNumber instanceof Double) {

boolean greaterThanOtherNumber = yourNumber.doubleValue() > otherNumber.doubleValue();

// [...]

}

注意:不一定需要.compareTo()检查-取决于您要比较它们的精确程度。 您当然可以始终使用.doubleValue(),因为每个数字都应提供此处列出的方法。

编辑:如评论中所述,您将(始终)必须检查BigDecimal和朋友。 但是他们提供了.compareTo()方法:

if(yourNumber instanceof BigDecimal && otherNumber instanceof BigDecimal) {

boolean greaterThanOtherNumber = ((BigDecimal)yourNumber).compareTo((BigDecimal)otherNumber) > 0;

}

Tedil answered 2019-12-31T20:57:30Z

1 votes

您可以简单地使用Number's doubleValue()方法进行比较; 但是,您可能会发现结果不够准确,无法满足您的需求。

Steven Mackenzie answered 2019-12-31T20:57:50Z

1 votes

这个如何? 绝对不好,但是它处理了所有必要的情况。

public class SimpleNumberComparator implements Comparator

{

@Override

public int compare(Number o1, Number o2)

{

if(o1 instanceof Short && o2 instanceof Short)

{

return ((Short) o1).compareTo((Short) o2);

}

else if(o1 instanceof Long && o2 instanceof Long)

{

return ((Long) o1).compareTo((Long) o2);

}

else if(o1 instanceof Integer && o2 instanceof Integer)

{

return ((Integer) o1).compareTo((Integer) o2);

}

else if(o1 instanceof Float && o2 instanceof Float)

{

return ((Float) o1).compareTo((Float) o2);

}

else if(o1 instanceof Double && o2 instanceof Double)

{

return ((Double) o1).compareTo((Double) o2);

}

else if(o1 instanceof Byte && o2 instanceof Byte)

{

return ((Byte) o1).compareTo((Byte) o2);

}

else if(o1 instanceof BigInteger && o2 instanceof BigInteger)

{

return ((BigInteger) o1).compareTo((BigInteger) o2);

}

else if(o1 instanceof BigDecimal && o2 instanceof BigDecimal)

{

return ((BigDecimal) o1).compareTo((BigDecimal) o2);

}

else

{

throw new RuntimeException("Ooopps!");

}

}

}

b_erb answered 2019-12-31T20:58:10Z

0 votes

假设您有一些类似的方法:

public T max (T a, T b) {

...

//return maximum of a and b

}

如果您知道只有整数,可以将long和double作为参数传递,则可以将方法签名更改为:

public T max(double a, double b) {

return (T)Math.max (a, b);

}

这将适用于字节,短,整数,长和双精度。

如果您假定可以传递BigInteger或BigDecimal或浮点数和双精度数的组合,则无法创建一种通用方法来比较所有这些类型的参数。

Roman answered 2019-12-31T20:58:43Z

0 votes

如果您的Number实例绝不是Atomic(即AtomicInteger),则可以执行以下操作:

private Integer compare(Number n1, Number n2) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {

Class extends Number> n1Class = n1.getClass();

if (n1Class.isInstance(n2)) {

Method compareTo = n1Class.getMethod("compareTo", n1Class);

return (Integer) compareTo.invoke(n1, n2);

}

return -23;

}

这是因为所有非原子Number都实现了可比

编辑:

由于反思,这很昂贵:我知道

编辑2:

当然,这种情况不会出现您想将小数与整数或类似数字进行比较的情况。

编辑3:

假设没有Number的自定义后代没有实现Comparable(感谢@DJClayworth)

Yaneeve answered 2019-12-31T20:59:34Z

0 votes

System.out.println(new BigDecimal(0.1d).toPlainString());

System.out.println(BigDecimal.valueOf(0.1d).toPlainString());

System.out.println(BigDecimal.valueOf(0.1f).toPlainString());

System.out.println(Float.valueOf(0.1f).toString());

System.out.println(Float.valueOf(0.1f).doubleValue());

t _ liang answered 2019-12-31T20:59:49Z

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中,可以使用数据库查询语言(如SQL)来实现两个表的重复性验证。具体的实现方式取决于你使用的数据库类型和表结构,以下是一个通用的示例: 1. 首先,确定两个表之间的关联字段(即用于验证重复性的字段)。假设我们有两个表:表A和表B,它们都有一个名为"identifier"的字段,用于验证重复性。 2. 使用SQL编写查询语句来检查重复性。例如,可以使用以下查询语句: ```sql SELECT COUNT(*) FROM tableA WHERE identifier = 'your_value'; ``` 这将返回与给定匹配的记录数。 3. 在Java中,使用JDBC(Java数据库连接)或任何ORM(对象关系映射)框架来执行该查询语句。以下是一个使用JDBC进行查询的示例代码: ```java // 导入所需的类 import java.sql.*; // 创建数据库连接 Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/your_database", "username", "password"); // 创建查询语句 String query = "SELECT COUNT(*) FROM tableA WHERE identifier = ?"; // 创建预编译语句 PreparedStatement statement = connection.prepareStatement(query); statement.setString(1, "your_value"); // 执行查询 ResultSet resultSet = statement.executeQuery(); // 处理结果 if (resultSet.next()) { int count = resultSet.getInt(1); if (count > 0) { System.out.println("重复性验证失败"); } else { System.out.println("重复性验证通过"); } } // 关闭连接 resultSet.close(); statement.close(); connection.close(); ``` 请注意,上述示例中的连接字符串和数据库凭据应根据你的实际情况进行修改。 这只是一个简单的示例,具体的实现方式可能因数据库类型、表结构和项目需求而有所不同。但是,基本思路是使用SQL查询语句来检查重复性,并在Java中执行该查询以获取结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值