こんにちは、もちきなこです。本日は、コーディング学習のため、基本的な入出力について気づいたこと、調べたことをまとめていきたいと思います。転職活動は無事内定をもらい終了したのですが、お見送りの企業様から、実務的なコーディング経験の少なさ(javaなどのオープン系言語)を指摘されておりました。そのため、少しでも、実務に入った時にコーディングがスムーズにいくように、少しずつ問題を解いていこうと思っております。
Scanner
インポート文は、
import java.util.Scanner;
型を指定しての受け取り方が複数あり、主に下記のような内容。
//標準入力(キーボード等)の受付
Scanner sc = new Scanner(System.in);
/**
*下記3つは空白を含まない
*/
//int型(整数型)での値受け取り
int num = sc.nextInt();
//double型(小数型)での値受け取り
double doubleNum = sc.nextDouble();
//String型(文字列型)での値受け取り
String text = sc.next();
/**
*下記は空白を含んだ1行
*/
//String型(文字列型)での値受け取り
String textLine = sc.nextLine();
上記に関して、黄色部分(空白を含まないもの)を使用した後に赤色部分(空白を含むもの)を呼び出すと、「黄色部分を使用した残りの空白と改行(ゴミ)」が行に残っているため、想定通りの挙動が行われない可能性があります。そのため、黄色部分の後に、赤色部分を使用する場合には、その取得した行数分空取得し処理を始める、もしくは、全て「nextLine()」で取得してから処理を始める等の対処をする必要があります。
そして、入出力後の処理の最後には、下記クローズ文を宣言する必要があります。
sc.close();
ただし、上記クローズ文を宣言した後に、同じプログラムで再度標準入力を呼び出すとエラーが発生するため、必ずプログラム内での入出力処理が完全に終わってからクローズ文を書きましょう。
余談ですが、javaは、openやcloseの概念がわかりにくく感じます。というのも、明示的に自分のコード内でopenを使用しているわけではなく、ファイル操作クラス等のインスタンスを作成する際にopen処理が行われ、自分のコード内でopen処理を記述する機会が少ない(間接的にはnewなどで記述している)からです。close処理に関しては、使用するクラスによってScannerクラスのように記述することがあるため、タイミングは気を付けなければいけませんが、記述する機会はopenよりかはあると思います。基本的には、COBOLの言語などと同様に、リソースを使用する際には「open」、リソースを使い終わったら「close」すると覚えておきましょう(それでもclose処理は忘れがちなので気を付けます)。
そして、Scannerクラスは、上記のように便利な反面、大量のデータを一度に処理する際に、処理速度が遅く、メモリを食います。そして、使用する環境(version等)によっては使えない場合があります。その部分は意識をしながら、Scannerクラスを使っていきましょう。
BufferedReader
インポート文は、下記で、「BufferedReader」クラスを使用することにより、行単位でのデータの読み込みができます。「InputStreamReader」クラスは、文字列を読み書きするために行うストリームを読み込むことができます(バイト指向のコンピュータに適したストリームを文字エンコーディングを指定することで、文字指向のストリームに変換する(人が理解しやすい文字列に変換する))。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
基本的な使用方法は、
BufferedReader bd = new BufferedReader(new InputStreamReader(System.in));
String text = bd.readLine();
BufferedReaderは、内部的にバッファ(一定サイズのメモリ領域)を持ち、一度にまとめて読み込み、データがたまってからまとめて処理を行う(バッファリング機能がある)ため、処理速度が速いです。「readLine」が呼び出されたときに、バッファにデータがあれば、そこから読み込みます。空ならデータをReaderから呼び出し、バッファに格納してから、バッファからデータを読み込みます。
基本的には、文字列型として1行ずつ読み込むため、大量のデータを処理するのに適しています。標準入力以外にもファイルやDBなどの幅広い入力ソースに対応できますが、例外処理や型変換などが必須で、コードが煩雑になりやすいです。
ScannerとBufferedReaderどっちが良い?
処理速度や応用性の高さでいうと、「BufferedReader」クラスがいい。大量のデータを一度に処理がしやすく、ファイルや幅広い入力ソースに対応できる。それに加えて、基本的にversionが古くても対応しているため、どの環境でも利用しやすい。ただし、型変換や例外処理が必須のため、処理が煩雑になりやすく、コードを記述するのに時間がかかるというデメリットがある。
処理の簡単さの面でいうと、「Scanner」クラスがいい。型をデータ読み込み時から指定できるため、処理が容易で、コードの記述が短くて済む。ただし、大量のデータを一度に処理する際に、処理速度が遅く、メモリを食います。そして、使用する環境(version等)によっては使えない場合があり、標準入力に特化しているというデメリットがある。
上記のような点から、エンジニアのコーディングという観点からみれば、記述は複雑ではありますが、「BufferedReader」クラスを利用したコードを記述できると、コーディングのレベルアップがしやすく、複雑な大量のデータを処理することになったとしても、安定した処理を記述できるようになると思います。
私は現在、アルゴリズムの考え方を主に習得することを目的にコードを書いているので「Scanner」クラスを使用していますが、より実務的な観点からみて「BufferedReader」クラスを使用してコードを書けるようにシフトしていきたいと思います。
コメント