↓↓クリックして頂けると励みになります。
【12 | 並び替え】 << 【ホーム】 >> 【14 | クラスメソッド】
Javaのメソッド(method)は、クラスやオブジェクトに属する処理や機能の塊です。
メソッドは特定の動作を実行するため、主に以下のような目的で使用されます。
- コードの再利用性を高めるために、一連の処理をまとめる。
- プログラムの構造をより整理し、理解しやすくする。
- 特定の処理を簡単に呼び出し、再利用する。
Javaのメソッドは、メソッド名、引数、戻り値、およびメソッド本体から構成されます。
一般的なメソッドの宣言形式は次のようになります。
修飾子 戻り値の型 メソッド名(引数の型 引数名, ...) { // メソッドの本体 // 処理内容 return 戻り値; // 戻り値がある場合 }
これらの要素について説明します。
- 修飾子(Modifiers): メソッドがアクセス可能であるかどうかを制御するキーワードです。例えば、public、private、protected、staticなどがあります。
- 戻り値の型(Return Type): メソッドが返すデータの型です。voidは戻り値がないことを示します。
- メソッド名(Method Name): メソッドの識別子です。
- 引数の型(Parameter Types): メソッドが受け取るデータの型です。メソッドが引数を受け取らない場合、この部分は空になります。
- 引数名(Parameter Names): メソッドが受け取るデータの名前です。
- 戻り値(Return Value): メソッドが返す値です。戻り値がない場合は、voidを使用します。
- メソッド本体(Method Body): メソッドが実際に実行するコードのブロックです。
メソッドはある特定の一連の処理をまとめたプログラムの構造の1つで、以下のルールがあります。
- メソッドは必ずクラスの内部に記述しなければいけません。
- 一つのクラスの中にメソッドは何個でも自由に記述できます。
- メソッドを記述する順序は処理の順序とは全く関係ありません。
- メソッドの名前は自由に付けることができます。
- 習慣では小文字のアルファベットで始まり、長い名前のメソッドの場合には単語の区切りは大文字で表します。
Visual Studio Codeで以下の「Sort3.java」ファイルを作成して下さい。
新規作成 【Sort3.java】
public class Sort3 { private static int[] test = { 10, 75, 24, 32, 98, 72, 88, 43, 60, 35, 54, 62, 2, 12, 82, }; public static void main( String[] args ) { sort( test ); for( int i=0; i<test.length; i++ ) { System.out.println( (i+1) + ":" + test[i] ); } } public static void sort( int[] array ) { for ( int i=0; i<array.length-1; i++ ) { maxN( array, i ); } } public static void maxN( int[] array, int n ) { int max = array[n]; int maxIndex = n; for( int i=n+1; i<array.length; i++ ) { if( array[i] > max ) { max = array[i]; maxIndex = i; } } array[maxIndex] = array[n]; array[n] = max; } }
このプログラムにはメソッドが3つあります。
1つめはsort( )
、2つめはmaxN( )
、もう1つはmain( )
です。
実はmain( )
もメソッドなのです。
メソッドの中で、main( )
メソッドが必ず一番最初に処理されます。
public static void メソッド名( 引数 ) { }
publicは公開するといった意味があります。
一番最初に宣言する項目です。
次にstaticは静的なという意味があります。
staticを宣言すると、そのメソッドの値をどんどん書き換えて処理させるといったことができなくなります。
voidは戻り値が無いメソッドであるということを宣言する型です。
void型と言います。
int型やfloat型と同じように型の一つです。
int型は整数値で返すといった意味を持っています。
それに対してvoid型は返す値が無いということです。
メソッド名の後の括弧( )の中に引数を入れます。
引数はメソッドの呼び出しの時に入れる引数とイコールの関係を持っています。
ではプログラムを見てみましょう。
main()
メソッドの中に次の記述があります。
sort( test );
これがメソッドの呼び出しです。
このようにメソッドを呼び出すには、メソッド名とその括弧( )
の中に与えたい引数を記述します。
sort( test )
が読み込まれると、そのメソッドが処理されます。
public static void sort( int[] array ) { for ( int i=0; i<array.length-1; i++ ) { maxN( array, i ); } }
引数にtestを使っているので、それがarrayに渡されます。
int[] array = int[] test;
このメソッドの中では、testがarrayとなって処理されるのです。
このメソッドではすぐfor文でループすることになります。
ループするごとに今度はmaxNメソッド
が呼び出されています。
引数はarray
と i
です。
引数を記述する前に型の宣言(int[] array
とint i
)が行われているので、呼び出すときは(array, i)
というように型を記述する必要はありません。
次にmaxNメソッド
を説明します。
public static void maxN( int[] array, int n ) { int max = array[n]; int maxIndex = n; for( int i=n+1; i<array.length; i++ ) { if( array[i] > max ) { max = array[i]; maxIndex = i; } } array[maxIndex] = array[n]; array[n] = max; }
sortメソッドから渡された引数は以下のように代入されます。
int[] array = int[] array; int n = int i;
後の処理は「Sort.java」で説明した通りで、一番大きな数字を探して前の方と入れ替える作業をします。
それらの作業を受けてmainメソッドでは出力する作業のみを行っています。
コンパイルして出力結果を確認します。
~/Desktop/Programming/JP $ javac Sort3.java ~/Desktop/Programming/JP $ java Sort3 1:98 2:88 3:82 4:75 5:72 6:62 7:60 8:54 9:43 10:35 11:32 12:24 13:12 14:10 15:2
Visual Studio Codeで以下の「Sort4.java」ファイルを作成して下さい。
新規作成 【Sort4.java】
public class Sort4 { private static int[] test = { 10, 75, 24, 32, 98, 72, 88, 43, 60, 35, 54, 62, 2, 12, 82, }; public static void main( String[] args ) { sort( test ); for( int i=0; i<test.length; i++ ) { System.out.println( (i+1) + ":" + test[i] ); } } public static void sort( int[] array ) { int tmp=0; for( int i=0; i<array.length-1; i++ ) { for( int j=0; j<array.length-i-1; j++ ) { if( array[j] < array[j+1] ) { tmp = array[j]; array[j] = array[j+1]; array[j+1] = tmp; } } } } }
このプログラムは「Sort2.java」をmainメソッド
とsortメソッド
に分けて書き直したプログラムです。
作業ごとにメソッドを分けるとプログラムが見やすくなるというメリットがあります。
Javaプログラムをコンパイルして実行結果を確認します。
~/Desktop/Programming/JP $ javac Sort4.java ~/Desktop/Programming/JP $ java Sort4 1:98 2:88 3:82 4:75 5:72 6:62 7:60 8:54 9:43 10:35 11:32 12:24 13:12 14:10 15:2
Visual Studio Codeで以下の「Sort5.java」ファイルを作成して下さい。
新規作成 【Sort5.java】
public class Sort5 { private static int[] test = { 10, 75, 24, 32, 98, 72, 88, 43, 60, 35, 54, 62, 2, 12, 82, }; private static int[] tmp = null; public static void main( String[] args ) { sort( test ); for( int i=0; i<test.length; i++ ) { System.out.println( (i+1) + ":" + test[i] ); } } public static void sort( int[] array ) { sort( array, 0, array.length-1 ); } public static void sort( int[] array, int min, int max ) { if( ( max - min ) < 5 ) { sort2( array, min, max ); return; } if( tmp == null ) tmp = new int[ array.length ]; float m = average( array, min, max ); int largeCount=0; int smallCount=0; for( int i=min; i<=max; i++ ) { if( array[i] > m ) { tmp[ min+largeCount ] = array[i]; largeCount++; } else { tmp[ max-smallCount ] = array[i]; smallCount++; } } for( int i=min; i<=max; i++ ) { array[i] = tmp[i]; } sort( array, min, min+largeCount-1 ); sort( array, max-smallCount+1, max ); } private static void sort2( int[] array, int min, int max ) { for( int i=min; i<max; i++ ) { for( int j=min; j<max-(i-min); j++ ) { if( array[j] < array[j+1] ) { int tmp = array[j]; array[j] = array[j+1]; array[j+1] = tmp; } } } } private static float average( int[] array, int min, int max ) { float sum = 0.0f; for( int i=min; i<=max; i++ ) { sum += array[i]; } return sum/( max - min + 1); } }
「private static int[ ] tmp = null;
」はこのあとtmp[ ]
を使えるようにここで定義しています。
作業領域用データを作成しているだけです。
nullは何もないという意味です。
まずmain( String[] args )
のsort(test)
から sort( int[] array ) {
に入ります。
ここでtest
がarray[]
に置き換わります。
なぜ同じsortメソッドなのにsort( int[] array, int min, int max ) メソッド
の方に処理が移らないかというと、メソッドの引数の数に理由があります。
引数が1つしかないので、同じsortメソッド
ですがsort( int[] array )
の方に処理が移るのです。
sort( int[] array )
では、sort( array, 0, array.length-1 )
という様にして引数を3つ与える処理を行っています。
これにより sort( int[] array, int min, int max ) { }
に入ります。
ここでmin=0,max=14
に置き換わります。(今回のプログラムのみ。与えられるtest[]
の数によって異なります。)
min=0,max=14
ですので最初はif( ( max - min ) < 5 )
の条件に当てはまらず、if( tmp == null )
が呼び出されtemp=array.length
となります。
ここでtmp = new int[ array.length ];
について説明します。
new演算子
は新しくメモリーを確保するときに用います。
プログラムで配列や変数を扱うときには必ずメモリーを確保しなければなりません。
int[ ] test
では直接配列に数字を代入しているので、自動的にメモリが確保されています。
しかし今回のint[] tmp
ではnull
を指定しているので、この時点でメモリはまだ確保されていません。
自分でメモリを確保する必要があります。
配列のメモリの確保の仕方は次のように行います。
int[] 配列名 = new int[確保メモリ数];
intの部分は型名なので、その時の状況により異なります。
次にfloat m = average( array, min, max );
よりfloat average( int[] array, int min, int max )
が呼び出され、i=0〜14
まで繰り返します。
データの平均が出てreturnします。
ここで、float m = 平均値
となります。
returnについて詳しく説明します。
averageの型がfloatになっているのに注目してください。
今まではvoid型のメソッドしか扱っていませんでした。
void型は戻り値がありませんのでreturn文は使用しません。
しかしメソッドの型を戻り値があるような型に指定している場合、return文を使って戻り値を返さなければなりません。
今回の場合は、return sum/( max - min + 1);
という記述がこの処理にあたります。
戻り値としてsum/( max - min + 1)
という値を返しています。
わかりやすく書くと次のようになります。(実際このように書き換えるとプログラムは動きません。)
float average( int[] array, int min, int max ) = sum/( max - min + 1);
それが、sortメソッドに戻り、
float m = average( int[] array, int min, int max )
が
float m = sum/( max - min + 1)
という形に書き換えて考えることができます。
float型には数字の最後にf
をつけます。
これは決まりなので覚えてください。
次の記述を見てください。
if( array[i] > m ) { tmp[ min+largeCount ] = array[i]; largeCount++; } else { tmp[ max-smallCount ] = array[i]; smallCount++; }
これにより平均値より大きいものはtmp[0]
から順に入っていき、小さいものはtmp[14]
かtmp[13],tmp[12]・・
と入っていきます。
0〜14まで調べると次に進みます。
for( int i=min; i<=max; i++ ) { array[i] = tmp[i]; }
これにより配列tmp[]
の値が配列array[]
に代入されます。
sort( array, min, min+largeCount-1 );
によりmin=0,max=largeCount-1
となり、再びsort( int[] array, int min, int max )
に入ります。
同時にsort( array, max-smallCount+1, max );
によりmin=max-smallCount+1
、max=14
となり sort( int[] array, int min, int max )
に入ります。
この時点で2つのブロックに分けられました。
そしてこの2つに分けられたブロックのそれぞれの平均値が出され、それよりも大きいもの、小さいものに分けられます。
この時点で4つのグループに分けられます。
そのとき、if( ( max - min ) < 5 )
の条件に当てはまり、sort2( array, min, max );
からsort2( int[] array, int min, int max )メソッド
に入りソート(並び替え)されます。
最後にmainに戻り結果がプリントされます。
この並び替えの特徴は、ブロックで分けることによりsort2で処理される並び替えの動作が少なくなることにあります。
ちょっと複雑ですが、並び替えは今までのプログラムより早くできます。
Javaプログラムをコンパイルして実行結果を確認します。
~/Desktop/Programming/JP $ javac Sort5.java ~/Desktop/Programming/JP $ java Sort5 1:98 2:88 3:82 4:75 5:72 6:62 7:60 8:54 9:43 10:35 11:32 12:24 13:12 14:10 15:2
Visual Studio Codeで以下の「Sort6.java」ファイルを作成して下さい。
新規作成 【Sort6.java】
public class Sort6 { private static int[] test = { 10, 75, 24, 32, 98, 72, 88, 43, 60, 35, 54, 62, 2, 12, 82, }; private static int[] tmp = null; public static void main( String[] args ) { sort( test ); for( int i=0; i<test.length; i++ ) { System.out.println( (i+1) + ":" + test[i] ); } } public static void sort( int[] array ) { sort( array, 0, array.length-1 ); } public static void sort( int[] array, int min, int max ) { if( ( max - min ) < 5 ) { sort2( array, min, max ); return; } if( tmp == null ) tmp = new int[ array.length ]; int size = max - min + 1; int half = size/2 + size%2; sort( array, min, min+half-1 ); sort( array, min+half, max ); int counter1 = 0; int counter2 = 0; for( int i=min; i<=max; i++ ) { if( counter1 > (half-1) ) { tmp[i] = array[ min+half+counter2 ]; counter2++; } else if( counter2 > (max-min-half) ) { tmp[i] = array[ min+counter1 ]; counter1++; } else if( array[ min+counter1 ] > array[ min+half+counter2 ] ) { tmp[i] = array[ min+counter1 ]; counter1++; } else { tmp[i] = array[ min+half+counter2 ]; counter2++; } } for( int i=min; i<=max; i++ ) { array[i] = tmp[i]; } } private static void sort2( int[] array, int min, int max ) { for( int i=min; i<max; i++ ) { for( int j=min; j<max-(i-min); j++ ) { if( array[j] < array[j+1] ) { int tmp = array[j]; array[j] = array[j+1]; array[j+1] = tmp; } } } } }
private static int[ ] tmp = null;
で作業領域用データtmp[ ]
を作ります。
まずmain( String[ ] args )
のsort(test)
から sort( int[ ] array ) {
にはいります。
ここでtest
がarray[ ]
に置き換わります。
sort( int[ ] array )
でsort( array, 0, array.length-1 )
により sort( int[ ] array, int min, int max )
に入ります。
ここでmin=0,max=14
に置き換わります。(今回のプログラムだけ)
最初はtmp = null
なので if ( tmp == null )
が呼び出されます。
int size=15,half=8
となり、sort( array, min, min+half-1 )
でmin=0,max=7
に、sort( array, min+half, max )
でmin=8,max=14
となり、それぞれまたsort( int[] array, int min, int max )
のループに入ります。
sort( array, min, min+half-1 )
ではmin=0,max=7
なので、またmin=0,max=3
とmin=4,max=7
の2つに分けられます。
sort( array, min+half, max )
ではmin=8,max=14
なので、min=8,max=11
とmin=12,max=14
の2つに分けられます。
それぞれ再びsort( int[] array, int min, int max )
のループに入ります。
ここで配列は次の4つの組に分けられています。
【1組】 10, 75, 24, 32
【2組】 98, 72, 88, 43
【3組】 60, 35, 54, 62
【4組】 2, 12, 82
return文 でループは終わります。
ここのreturn文は戻り値を返すためではなく、この処理を終わらせる意味を持っています。
このreturn文がないとこのメソッドの繰り返しループが永遠に繰り返されてしまい、最終的にはメモリを食い尽くしてしまう恐れがあります。
このreturn文があることで、sort( array, min, min+half-1 )
とsort( array, min+half, max )
のそれぞれの場所まで戻ります。
同じメソッドを繰り返して使うときは最後の処理の時にreturn文をつけないと、うまく動かなくなりますので気をつけてください。
ソートされた4組はループに入る前まで戻され(4つの組に分けられる前、もっと解りやすく言うと、まだ2つの組の時でsortメソッド
に入るとき)、min=0,max=7,
とmin=8,max=14
の2組がそれぞれfor( int i=min; i<=max; i++ )
のループにはいります。
2組は次のような順序になっている。
【1組 】75,32,24,10, 98,88,72,43,
【2組 】62,60,54,35, 82,12,2
これまでの流れを解りやすくしてみましたので参考にしてください。
処理A | size=15、min=0、max=14 | ||||||||||||||
array | [0] | [1] | [2] | [3] | [4] | [5] | [6] | [7] | [8] | [9] | [10] | [11] | [12] | [13] | [14] |
数字 | 10 | 75 | 24 | 32 | 98 | 72 | 88 | 43 | 60 | 35 | 54 | 62 | 2 | 12 | 82 |
これは、一番最初の状態です。
次にこれを半分にしてまたsortメソッドに入ると次のようになります。
処理B | size=8,min=0,max=7 | size=7,min=8,max=14 | |||||||||||||
array | [0] | [1] | [2] | [3] | [4] | [5] | [6] | [7] | [8] | [9] | [10] | [11] | [12] | [13] | [14] |
数字 | 10 | 75 | 24 | 32 | 98 | 72 | 88 | 43 | 60 | 35 | 54 | 62 | 2 | 12 | 82 |
この二つがそれぞれまたsortメソッドに入って半分にされると次のように4分割されます。
処理C | size=4,min=0,max=3 | size=4,min=4,max=7 | size=4,min=8,max=11 | size=3,min=12,max=14 | |||||||||||
array | [0] | [1] | [2] | [3] | [4] | [5] | [6] | [7] | [8] | [9] | [10] | [11] | [12] | [13] | [14] |
数字 | 10 | 75 | 24 | 32 | 98 | 72 | 88 | 43 | 60 | 35 | 54 | 62 | 2 | 12 | 82 |
これがまたそれぞれsortメソッドに入るのですが、ここで今まで当てはまらなかった次の条件の処理に移ります。
if( ( max - min ) < 5 ) { sort2( array, min, max ); return; }
これにより、4つのブロックのそれぞれが並び替えされ次のようになります。
処理C | size=4,min=0,max=3 | size=4,min=4,max=7 | size=4,min=8,max=11 | size=3,min=12,max=14 | |||||||||||
array | [0] | [1] | [2] | [3] | [4] | [5] | [6] | [7] | [8] | [9] | [10] | [11] | [12] | [13] | [14] |
数字 | 75 | 32 | 24 | 10 | 98 | 88 | 72 | 43 | 62 | 60 | 54 | 35 | 82 | 12 | 2 |
この並び替えが終わったらreturn文によりこのメソッドループが終わります。
このメソッドのループを再帰的ループといいます。
このreturn文によりどこまで処理が戻るかというと、処理Bのところまで戻ります。
戻ったら次のようになっています。
処理B | size=8,min=0,max=7 | size=7,min=8,max=14 | |||||||||||||
array | [0] | [1] | [2] | [3] | [4] | [5] | [6] | [7] | [8] | [9] | [10] | [11] | [12] | [13] | [14] |
数字 | 75 | 32 | 24 | 10 | 98 | 88 | 72 | 43 | 62 | 60 | 54 | 32 | 82 | 12 | 2 |
この2つのブロックがそれぞれ次のfor文の処理に移ります。
int counter1 = 0; int counter2 = 0; for( int i=min; i<=max; i++ ) { ・ ・ ・
このfor文の処理を説明するのに、size=8,min=0,max=7
の配列{75,32,24,10,98,88,72,43}
の方の処理を見ながら説明します。
まず、couter1
とは[0]〜[3]
の配列{75,32,24,10}
を示します。
couter2
は[4]〜[7]
の配列{98,88,72,43}
を示します。
このif文の意味は、簡単に言うと両方のブロックの先頭同士をまず比べ(今回は75と98)、大きいほうをtmp[0]
に代入します。
代入したほうのブロックのcounterをひとつインクリメントします。
次は75と88を比べてといった処理をfor文で繰り返しているだけです。
この処理は、実際に数字を当てはめて見ていけば解りやすいです。
このループが全部終わると今度は処理Aに再び戻ります。
戻ったときには次のようになっています。
処理A | size=15、min=0、max=14 | ||||||||||||||
array | [0] | [1] | [2] | [3] | [4] | [5] | [6] | [7] | [8] | [9] | [10] | [11] | [12] | [13] | [14] |
数字 | 98 | 88 | 75 | 72 | 43 | 32 | 24 | 10 | 82 | 62 | 60 | 54 | 35 | 12 | 2 |
この2つのブロックがまた次のループに入ります。
int counter1 = 0; int counter2 = 0; for( int i=min; i<=max; i++ ) { ・ ・ ・
この処理が終わると、すべてが並び替えられていてmainメソッド
に戻り結果が出力されます。
コンパイルして実行結果を確認します。
~/Desktop/Programming/JP $ javac Sort6.java ~/Desktop/Programming/JP $ java Sort6 1:98 2:88 3:82 4:75 5:72 6:62 7:60 8:54 9:43 10:35 11:32 12:24 13:12 14:10 15:2
【12 | 並び替え】 << 【ホーム】 >> 【14 | クラスメソッド】
↓↓クリックして頂けると励みになります。