2013-02-23 9 views
5

Math.maxの実装がvariadic functionでないのはなぜですか?なぜMath.max(double a、double b)varadicはありませんか?

それはこのように実装され得ることができます:

public class Main { 
    public static double max(double... values) { 
     double max = Double.NEGATIVE_INFINITY; 
     for (double tmp : values) { 
      max = max < tmp ? tmp : max; 
     } 
     return max; 
    } 

    public static void main(String[] args) { 
     // This works fine: 
     System.out.println(max(-13, 12, 1337, 9)); 

     // This doesn't work: 
     // System.out.println(Math.max(-13, 12, 1337)); 
    } 
} 

は、それがこのように実装されていない理由理由はありますか?

+4

数学は、Java 1.0で導入されました。 1.5のVarargs ... – Kai

答えて

3

なぜMath.maxはバリデーションではないのですか?他の人は、バリデーシックな機能が導入されたときにそのようなメソッドが作成されない理由については答えていません。

私も(open bug-reportあります)それを知らないので、私は推測することができます。

それはMathに実装されていないことは事実であるが、私たちはCollectionsに見れば次のような方法があります:

public static <T extends Object & Comparable<? super T>> T max(
    Collection<? extends T> coll) { 
    ... 
} 

型シグネチャは、(それが共変性と反変性を処理するのに十分に柔軟である必要がある)醜いながら全ての機能がわずかに異なる場所で、実施された後、それは容易Collections.max(Arrays.asList(-13, 12, 1337, 9));と共に使用することができます。

さらに良い:このメソッドはdouble型だけでなく、Comparableインターフェイスを実装するすべての型を処理できます。

あなたの提案された解決策も、Collectionsの解決策もオブジェクト指向ではありませんが、それらは単に静的メソッドです。幸いにもJDK8と、これは変更されます。

import java.util.Arrays; 
import java.util.List; 
import java.util.Optional; 

int max(List<Integer> list) { 
    Optional<Integer> opt = list.stream().max((a,b) -> a-b); 
    return opt.orElse(Integer.MAX_VALUE); 
} 

max(Arrays.asList(-13, 12, 1337, 9)); // 1337 
max(Arrays.asList()); // 2147483647 

をコレクションライブラリは、より多くのオブジェクト指向であることをProject Lambdaに再加工され、今後のリリースでは。上記の例では、Lambdaを使用して、max要素を簡単かつ判読可能な方法で確認しています。以下は、あまりにも動作します:

import static java.util.Comparators.naturalOrder; 

Arrays.asList(-13, 12, 1337, 9) 
    .stream() 
    .max(naturalOrder()) 
    .ifPresent(System.out::println); // 1337 

代わりのmax 1はまた、高階関数reduce使用することができます別の詳細

Arrays.asList(-13, 12, 1337, 9) 
    .stream() 
    .reduce((a,b) -> a > b ? a : b) 
    .ifPresent(System.out::println); // 1337 

Optionalの使用です。上記の例で示したように、上位関数の構成によるエラー処理を簡素化するための型です。それはそれは多型である

  • オブジェクト指向され

    1. ラムダ提案は、それが不要Math.maxの可変引数フォームを実装するために作るいくつかの利点があります。これは、それは、オンザフライでの並列化できます

    2. を理解することは、表現と簡単です
    3. (などIteratorListSetStream)それは、コレクションのすべてのタイプで使用できることを意味します。ちょうど変更する.stream().parallelStream()
  • 2

    バリデーション関数より長いためにJavaに存在していた(java 5に導入されています)、あなたが今見たように、それを更新する必要はあまりありませんでした。また、配列(ダブル[])として可変引数メソッドに関与そこのahiddenパフォーマンスペナルティがjava.lang.Mathが長い可変引数関数の前に、JDK 1.0で導入された舞台裏であなたの引数

    +0

    あなたはvariadic関数を持つJavaのバージョンを知っていますか? 別の質問: 'max(double ... values)'と 'max(double a、double b)'があれば、どのような関数を取るべきですか?私はそれを試して、それは非variadicものを取るが、私はJLSでそれを見つけることはなかった。 –

    +0

    @moose - java 5(私はリンクを含んでいます)。また、dasblinkenlightとして、varargメソッドは実際には配列を受け入れるメソッドであると言っています - この場合はdouble []なので、2つの引数だけでは、非varargメソッドがより良い一致になります。 – radai

    5

    から作成されます

    Java 5の言語に導入されました。

    さらに、効率が懸念されます。ほとんどの場合、2つの要素が必要な場合、それらを保持する中間配列を作成せずに "インライン"に渡す方がはるかに高速です。これにより、実装内にループを設定するコストも削減されます。バックJDK 1.0に

    0

    Math.max()日付可変長引数の関数は、Java 5まで

    1

    を存在していないのに対し、Math.maxは、引数構文の変数#を導入した長い前に、JDK 1.0以降の周りされています。これは、あなたの提案した方法を更新することができなかったということではありません。ライブラリメソッドの定義や実装が変更されることもありますが、これはまれです。ほとんどの場合、既存のメソッドを変更するのではなく、新しいメソッドがクラスに追加されます。

    既存のメソッドと新しいvar argsメソッドが同じクラスに並んで存在する可能性があるため、Maxの新しい実装は実際にはメソッドのオーバーロードのケースです。したがって、既存のメソッドを確実に置き換えることはできますが、Mathクラスに追加することもできます。だから私はそれを加えるべきだと思う。既存のメソッドだけを残しておくことができるという事実は、新しい実装がもたらす可能性のあるパフォーマンスに関する懸念を取り除きます。

    Java nとJava n + 1の間で変更される可能性のある文化は、とにかく変化しています。たとえば、ファイルアクセスクラスとjava.sql.Connectionは、Java 7では現在AutoCloseableを実装しているため、Java 6からJava 7に変更されました。 Java 9は、実際にはproject jigsawの方法であるクラスからいくつかのメソッドを削除しようとしています。

    Math.maxが更新されていない正当な理由がないと思うことがあります。多分、今までそれを示唆した人はいなかったでしょう。これを読んでいますか、Mark Reinhold

    2

    Java 8は非常に柔軟なストリームで数値演算を実装しています。例:

    DoubleStream.of(-13, 12, 1337, 9).max().getAsDouble() 
    

    自家製ほど単純ではありませんが、まっすぐ前方、速く、より柔軟です。マルチコアを利用して例えば

    は、ただ一つの関数呼び出しを必要とする:

    stream.parallel().max().getAsDouble() 
    

    最大を見つけることさえもダブルで非常に高速であるので、この場合はかなり無意味 - 見るために、あなたは、ダブルスの何百万人を必要とします差はミリ秒です。 しかし、他の処理がある場合は、それらをすばやくスピードアップすることができます。

    それとも、また、単にシステムクラスを使用して、一度にすべての分、平均、合計などを見つけることができますが:

    DoubleSummaryStatistics stat = DoubleStream.of(-13, 12, 1337, 9).summaryStatistics(); 
    System.out.println(stat.getMin()); 
    System.out.println(stat.getAverage()); 
    System.out.println(stat.getMax()); 
    System.out.println(stat.getCount()); 
    System.out.println(stat.getSum()); 
    
    関連する問題