为什么不java。郎。数实施可比较的?[重复]
-
20-08-2019 - |
题
这个问题已经有一个答案在这里:
- 比较价值的两个通用的数字 12的答案
没有人知道为什么 java.lang.Number
未实现 Comparable
?这意味着你不能排序 Number
s Collections.sort
这似乎对我有点奇怪。
后讨论更新:
感谢所有帮助的反应。我做了 一些更多的研究关于这个主题.
最简单的解释为什么java。郎。数量没有实现的可比较的根源在变化无常的关切。
一位的审查, java.lang.Number
是抽象的超级种类型的 AtomicInteger
, AtomicLong
, BigDecimal
, BigInteger
, Byte
, Double
, Float
, Integer
, Long
和 Short
.在该列表, AtomicInteger
和 AtomicLong
不执行 Comparable
.
周围挖,我发现它不是一个好的做法来实现 Comparable
在可变的类型,因为的对象可以改变期间或之后的相比呈现的结果的比较没有用的。既 AtomicLong
和 AtomicInteger
都是可变的。API设计师们的深谋远虑到没有 Number
实施 Comparable
因为这会限制落实未来的亚型。事实上, AtomicLong
和 AtomicInteger
加入Java1.5长后 java.lang.Number
最初实施。
除了可变性,可能有其他考虑因素也在这里一个 compareTo
在执行情况 Number
必须促进所有数值 BigDecimal
因为它是能够容纳所有的 Number
子的类型。这意味着促进在学和业绩是有点不清楚到我,但我的直觉认为,解决缺憾.
解决方案
值得一提的是,以下表述:
new Long(10).equals(new Integer(10))
总是 false
, ,这往往旅行的每个人在某一点或另一个。这样不仅可以比不上任意的 Number
但你甚至不能确定如果他们是平等的,或者不。
此外,与真正的原始种类型(float
, double
),确定如果两个数值是相等的,是非常棘手,必须在可接受保证金的错误。尝试代码,如:
double d1 = 1.0d;
double d2 = 0.0d;
for (int i=0; i<10; i++) {
d2 += 0.1d;
}
System.out.println(d2 - d1);
你会留下一些小的差别。
所以回来的问题 Number
Comparable
.你会如何实现它吗?使用的东西喜欢 doubleValue()
不会很可靠。记住的 Number
亚型是:
Byte
;Short
;Integer
;Long
;AtomicInteger
;AtomicLong
;Float
;Double
;BigInteger
;和BigDecimal
.
可能你一个可靠的代码 compareTo()
方法不会变成一系列的如果实例声明? Number
实例只有六个方法向他们提供:
byteValue()
;shortValue()
;intValue()
;longValue()
;floatValue()
;和doubleValue()
.
所以我猜太阳由(合理的)决定, Number
s只是 Comparable
要实例。
其他提示
为答复,请参阅Java bugparade 错误4414323.你还可以找到一个讨论 comp.郎。java。程序员
引用自太阳的回应的错误的报告,2001年:
所有"数量"都没有可比性;可比较的假定总共订购的 数字是可能的。这甚至不是 真的浮点数;NaN (不多)既不少于, 大于,也不等于任何 浮点的价值,甚至本身。{浮动,双}.比较实施一个总 订购的不同的排序 浮点"<"和"=" 经营者。此外,作为目前 实现的,该子类的数量 都只相当于其他的实例 同一类。还有其他的 情况一样复杂的数字,在那里没有 标准的总体排序的存在, 虽然一个可能的定义。在 短,不论是否的一个子类 数是可比较的应该被留作 决定这一子类。
为了实施可比较的数量,你就得编写代码,用于每一个亚类对。其容易,而不是只允许子类实现可比性。
很可能是因为这将是相当低效率的比较数字只表示为其每一个号码可以适应允许这样的比较会BigDecimal.
相反,非原子类的数量实现可比较的本身。
原子的都是可变的,所以不能实现原子比较。
你可以使用 你可以从堡垒 比较数字使用其NumberComparator类。
NumberComparator numberComparator = new NumberComparator();
assertTrue(numberComparator.compare(12, 24) < 0);
assertTrue(numberComparator.compare((byte) 12, (long) 24) < 0);
assertTrue(numberComparator.compare((byte) 12, 24.0) < 0);
assertTrue(numberComparator.compare(25.0, 24.0) > 0);
assertTrue(numberComparator.compare((double) 25.0, (float) 24.0) > 0);
assertTrue(numberComparator.compare(new BigDecimal(25.0), (float) 24.0) > 0);
试图解决原来的问题(排序列数值),选择是宣布发言报名一般类型的延伸的数量和实现可比性。
是这样的:
<N extends Number & Comparable<N>> void processNumbers(List<N> numbers) {
System.out.println("Unsorted: " + numbers);
Collections.sort(numbers);
System.out.println(" Sorted: " + numbers);
// ...
}
void processIntegers() {
processNumbers(Arrays.asList(7, 2, 5));
}
void processDoubles() {
processNumbers(Arrays.asList(7.1, 2.4, 5.2));
}
没有标准的比较数字不同的类型。但是你可以写你自己的比较,并用它来建树形图<Number, Object="">,TreeSet<Number> 或集合。sort(列表<Number>,比较)或阵列。sort(数量[],比较);
写你自己的比较
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
public class NumberComparator implements Comparator {
@SuppressWarnings("unchecked")
@Override
public int compare(Number number1, Number number2) {
if (((Object) number2).getClass().equals(((Object) number1).getClass())) {
// both numbers are instances of the same type!
if (number1 instanceof Comparable) {
// and they implement the Comparable interface
return ((Comparable) number1).compareTo(number2);
}
}
// for all different Number types, let's check there double values
if (number1.doubleValue() < number2.doubleValue())
return -1;
if (number1.doubleValue() > number2.doubleValue())
return 1;
return 0;
}
/**
* DEMO: How to compare apples and oranges.
*/
public static void main(String[] args) {
ArrayList listToSort = new ArrayList();
listToSort.add(new Long(10));
listToSort.add(new Integer(1));
listToSort.add(new Short((short) 14));
listToSort.add(new Byte((byte) 10));
listToSort.add(new Long(9));
listToSort.add(new AtomicLong(2));
listToSort.add(new Double(9.5));
listToSort.add(new Double(9.0));
listToSort.add(new Double(8.5));
listToSort.add(new AtomicInteger(2));
listToSort.add(new Long(11));
listToSort.add(new Float(9));
listToSort.add(new BigDecimal(3));
listToSort.add(new BigInteger("12"));
listToSort.add(new Long(8));
System.out.println("unsorted: " + listToSort);
Collections.sort(listToSort, new NumberComparator());
System.out.println("sorted: " + listToSort);
System.out.print("Classes: ");
for (Number number : listToSort) {
System.out.print(number.getClass().getSimpleName() + ", ");
}
}
}
为什么这已经不好的想法吗?:
abstract class ImmutableNumber extends Number implements Comparable {
// do NOT implement compareTo method; allowed because class is abstract
}
class Integer extends ImmutableNumber {
// implement compareTo here
}
class Long extends ImmutableNumber {
// implement compareTo here
}
另一种选择可能已经宣布类数量实现可比性,省略compareTo执行情况,并实现它在一些类似整数,同时扔UnsupportedException在其他人一样AtomicInteger.
我的猜测是由于不执行具有可比性,它给予更多的灵活性,以实现类来实现。所有的共同的数字(Integer,长,双等)做实施可比较的。你仍然可以调用的集合。排序,只要该元素自己实现可比性。
看类层次。包装类似的长期、整数等,实现可比性,即一个整数,相当于一个整数和一个长相当于一个长期的,但是你不能混合。至少有这个仿制药的范例。我想回答您的问题"为什么".
byte
(原始)是一个 int
(primitive)。元的只有一个值的时间。
语言设计的规则允许这样做。
int i = 255
// down cast primitive
(byte) i == -1
一个 Byte
是不是一个 Integer
. Byte
是一个 Number
和一个 Integer
是一个 Number
. Number
对象可以有一个以上的价值在同一时间。
Integer iObject = new Integer(255);
System.out.println(iObject.intValue()); // 255
System.out.println(iObject.byteValue()); // -1
如果一个 Byte
是一个 Integer
和一个 Integer
是一个 Number
, 哪一个值会使用的 compareTo(Number number1, Number number2)
方法?