Java 7のドキュメントが見つかりません。Java 6についてしか見つけることができません。これはまだ迅速またはマージです。方法は誰でも知っていますか?メソッドのドキュメントを見つけるArrays.sort
in Java 7?
Java 7は、プリミティブにDual-Pivot Quicksortを使用し、オブジェクトにTimSortを使用します。
実装メモ:並べ替えアルゴリズムは、Vladimir Yaroslavskiy、Jon Bentley、およびJoshua BlochによるDual-Pivot Quicksortです。このアルゴリズムは、他のクイックソートを2次のパフォーマンスに低下させる多くのデータセットでO(n log(n))パフォーマンスを提供し、通常は従来の(1ピボット)クイックソート実装よりも高速です。
実装は、Python(TimSort)のTim Petersのリストソートから改作されました。これは、Peter McIlroyの「楽観的ソートと情報理論的複雑さ」からのテクニックを使用しています。離散アルゴリズム、pp 467-474、1993年1月。
Timsort は、「マージソートと挿入ソート」のハイブリッドです。
Java 6、 for Arrays.sort JDK6:
jon L. BentleyおよびM. Douglas McIlroyの「Engineering a Sort Function」、Software-Practice and Experience、Vol。 23(11)P. 1249-1265(1993年11月)
Object []またはコレクション(Collections.sort())の場合、マージソートが使用されます。
はい! ...そしてまた
現在のOpen JDK 実装Tim Sortは、通常、オブジェクトの配列をソートするために使用されます(つまり、 Arrays.sort(Object[])
およびフレンド)-プリミティブ配列(_Arrays.sort
_メソッド)さまざまな他のメソッドが使用されます。
プリミティブの場合、ヒューリスティックは、クイックソート、マージソート、カウントソートなどのソート方法varietyの中から選択します3。ソートされるデータに応じて。これらの決定のほとんどは、並べ替えられる配列のタイプとサイズに基づいて単純に前もって行われますが、int
およびlong
要素の場合、決定は実際に、アレイ。したがって、多くの場合、適応/イントロスペクション(アルゴリズムを選択するヒューリスティック)に加えて、適応/イントロスペクション(TimSortまたは類似のマージソート)があります。
Tim Sortは、ユーザーがシステムプロパティ_Java.util.Arrays.useLegacyMergeSort
_をtrueに設定してレガシー動作を明示的に要求しない限り、Arrays.sort(Object[] a)
などのほとんどの種類のオブジェクトに使用されます。
プリミティブの場合、状況はより複雑になります。少なくともJDK 8(バージョン_1.8.0_111
_)以降では、並べ替えられる配列のサイズ、プリミティブ型、および配列の測定された「並べ替え」に応じて、さまざまなヒューリスティックが使用されます。概要は次のとおりです。
DualPivotQuicksort.INSERTION_SORT_THRESHOLD
_を参照)。このしきい値はalsoです。マージまたはクイックソートが使用され、サブ配列のサイズがしきい値を下回ったときに発生するサブ配列をソートするときに使用されます。そのため、挿入ソートの何らかの形式がすべてのソートで使用され、小さな配列の場合は、使用される唯一のアルゴリズムです。byte
、short
、およびchar
の場合、大規模な配列には counting sort が使用されます。これはO(n + range)
時間を要する単純なソートです。ここで、range
はバイト(256)またはshort/char(65536)値の総数です。並べ替えにはrange
値の基になる配列の割り当てが含まれるため、並べ替える要素の数が範囲全体のかなりの部分を占める場合にのみ使用されます。特に、29要素を超えるバイト配列(つまり、範囲の〜11%)、および3200要素を超えるshort/char配列(範囲の〜5%)に使用されます。int
およびlong
配列の場合、および挿入ソートのしきい値を超えるおよびカウントするソートしきい値未満のshort
/char
配列の場合、1つデュアルピボットクイックソートまたはマージソートの2つのアルゴリズムを使用できます。どちらを使用するかは、配列の並べ替えの程度によって異なります。入力は、昇順または降順の要素のrunsに分割されます。そのような実行の数が66を超える場合、配列はほとんどソートされていないと見なされ、デュアルピボットクイックソートでソートされます。それ以外の場合、配列はほとんどソートされていると見なされ、mergesortが使用されます(すでに列挙されているrunを開始点として使用します)。ideaランを検索し、次にmergesortを使用してそれらをソートすることは、いくつかの違いはありますが、実際にはTimSortに非常に似ています。したがって、少なくとも一部のパラメーターでは、JDKは実行対応のマージソートを使用していますが、パラメーターの他の多くの組み合わせでは、異なるアルゴリズムを使用しており、合計で少なくとも5つの異なるアルゴリズムが使用されています。
_Object[]
_とプリミティブの異なるソート動作の背後にある理由は、おそらく少なくとも2つあります。
1)_Object[]
_のソートはstableである必要があります。等しくソートされたオブジェクトは、入力と同じ順序で表示されます。プリミティブ配列の場合、そのような概念はありません。プリミティブはその値によって完全に定義されるため、安定したソートと不安定なソートは区別されません。これにより、プリミティブソートは、速度を優先して安定したアルゴリズムの必要性を省くことができます。
2)_Object[]
_のソートにはObject.compare()
メソッドが必要であり、これは任意に複雑で高価になる可能性があります。 compare()
メソッドが単純な場合でも、並べ替えメソッド全体をインライン化できない限り、通常はメソッド呼び出しのオーバーヘッドが発生します。2。したがって、ある種の_Object[]
_は、アルゴリズムがさらに複雑になるという犠牲を払っても、一般的には、全体の比較を最小限に抑えるようにバイアスされます。
一方、プリミティブ配列のソートは、通常1サイクルまたは2オーダーのプリミティブ値を直接比較するだけです。この場合、比較のコストと周囲のアルゴリズムの両方を考慮してアルゴリズムを最適化する必要があります。
少なくともJava 7とJava 9の間のバージョンの場合、Open JDKに基づいているため、これにはOracleのJDKも含まれます。可能性が高い他の実装でも同様のアプローチが使用されているが、チェックしていない。
1 バイト配列の場合、挿入ソートのしきい値は、カウントソートが使用される下限のカットオフであるため、実質的に29要素です。
2 非常に大きいため、これはありそうにありません。
3 カウントソートは、16ビット以下の比較的制限された範囲の値にのみ使用されます:byte
、short
またはchar
。
はい、Java 7はArrays.sortにTimsortを使用します。これがコミットです: http://hg.openjdk.Java.net/jdk7/jdk7/jdk/rev/ bfd7abda8f79