が記載されていないのはなぜjava.lang.番号の実施に匹敵?[重複]

StackOverflow https://stackoverflow.com/questions/480632

  •  20-08-2019
  •  | 
  •  

質問

この質問に答えはこちら

なんだろうけど、日本人はなぜ java.lang.Number な実施 Comparable?することはできませんう Numbers Collections.sort ようやく少し不思議に思います。

ポスト議論更新

全体的にも対応。その結う あまり研究についてこのテーマ.

最も簡単な説明がなぜjava.lang.ない数での実施を比較するに根ざした可変性です。

チェックインの見直し、 java.lang.Number の抽象スーパータイプの AtomicInteger, AtomicLong, BigDecimal, BigInteger, Byte, Double, Float, Integer, LongShort.このリスト AtomicIntegerAtomicLong るのはやめてください Comparable.

掘って発見されたではありませんので良い練習を実施 Comparable に変更可能な型のオブジェクト変更後の比較描画の比較の結果は、どちらがいいでしょうか?両 AtomicLongAtomicInteger は可変です。このAPIのデザイナーが制作した、何も考えない Number の実施 Comparable かい制約の実施が将来唆する。実際、 AtomicLongAtomicInteger 追加されたJava1.5長 java.lang.Number した。

ほからの可変性があると思われその他の注意事項同じことが言えます。A compareTo 実施中 Number が推進すべての数値を BigDecimal ることができるのでも全ての Number サブタイプ。の意味の推進の数学ライブパフォーマンスはビットのかが不明確であって、私の勘がそのソリューションのkludgy.

役に立ちましたか?

解決

でも、以下の式:

new Long(10).equals(new Integer(10))

常に false, になりがちな旅行の皆様かまいます。くだりすることはできない任意の比較 Numbersができないもの決定だけでなく、同等です。

また、実際のプリミティブ型(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() 方法なdevolveをつなぐ"のミッションの場合instanceof算はどこでわかりますか? Number インスタンスのみを行ない方法で入手している:

  • byteValue();
  • shortValue();
  • intValue();
  • longValue();
  • floatValue();や
  • doubleValue().

ね日の(合理的な決定する Numberわれたものとみ Comparable へのインスタンスです。

他のヒント

答えは、Java BugParadeのバグ4414323 のを参照してください。また、 COMPから議論を見つけることができます。 lang.java.programmerする

は、2001年からのバグレポートにSunの応答から引用すると:

  

すべての「数字」は比較することはできません。   同等のは、全体の順序付けを前提としてい   数字が可能です。これはさえません   浮動小数点数の場合はtrue。 NaNの   (非数)、よりどちらも小さく、   より大きく、またいかなるに等しいです   浮動小数点値もそのもの。   {フロート、ダブル}合計を課す.compare   順序が異なる注文   「<」と「=」浮動小数点の   演算子。また、現在のように   数の実装、サブクラス   他のインスタンスにのみ匹敵します   同じクラスの。他のがあります。   例、複素数のような、どこなし   標準の全順序が存在し、   が1を定義することができました。に   サブクラスのかどうか、短いです   番号は次のように同等のままにしておく必要がありさ   そのサブクラスの決定ます。

数に匹敵し実装するために、あなたはすべてのサブクラスのペアのためのコードを記述する必要があります。その容易なだけではなく、サブクラスがComparableを実装できるようになります。

非常におそらく数字を比較することではなく、非効率的になるので - 。あらゆる数のBigDecimalになり、このような比較を可能にするために収めることのできる唯一の表現を

の代わりに、数の非原子サブクラスが同等自体を実装します。

原子力のものは変更可能なので、アトミック比較を実装することはできません。

あなたはそのNumberComparatorクラスを使用して数値を比較するために Transmorph に使用することができます。

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));
}

異なる種類の数にはstardardの比較はありません。 あなたがあなた自身のコンパレータを書いて、TreeMapを<数、オブジェクト>、TreeSetの<番号>またはCollections.sort(一覧<番号>、コンパレータ)またはは、Arrays.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
}

別のオプションのAtomicIntegerのように他の人にUnsupportedExceptionを投げながらのcompareToの実装を省略し、クラス数がComparableを実装する宣言、および整数のようないくつかのクラスでそれを実装するためにされている可能性があります。

私の推測では、Comparableを実装していないことで、それはそれを実装するクラスを実装するか、しないように、より多くの柔軟性を与えるということです。すべての共通番号(整数、ロング、ダブル、など)Comparableを実装します。あなたはまだ限りの要素自体はComparableを実装してCollections.sortを呼び出すことができます。

クラス階層を見てみます。などロング、整数、などのラッパークラスは、Comparableを実装、すなわち整数は整数に匹敵する、と長い長いと同等ですが、あなたがそれらを混在させることはできません。このジェネリックパラダイムを有する少なくとも。どの私は「なぜ」あなたの質問に答えると思います。

byte(プリミティブ)int(プリミティブ)です。プリミティブは、一度に1つだけの価値を持っている。
言語設計ルールがこれを可能にする。

int i = 255

// down cast primitive
(byte) i == -1

A Byte Integerではありません。 Number compareTo(Number number1, Number number2)で、<=> <=>です。 <=>オブジェクトは、同時に複数の値を持つことができます。

Integer iObject = new Integer(255);
System.out.println(iObject.intValue());   // 255
System.out.println(iObject.byteValue());  // -1

<=> <=>あると<=>つの値は、あなたが<=>方法?

で使用する<=>、ある場合には
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top