LoginSignup
0
0

More than 3 years have passed since last update.

【Java】文字列結合・標準入力 (AOJ②複数の出力・テストケースの出力)

Last updated at Posted at 2020-11-14

AIZU ONLINE JUDGE の教材を使って勉強していきます

文字列結合

  • 文字列は演算子で結合できる
    • result += "bar";
    • builder.append("bar"); //めっちゃ早い
  • + で文字列を結合すると、元の文字列、連結する文字列、結果文字列の3個のString文字列を生成しているのでガベージコレクションの増大に。。
    • 元の文字列、連結する文字列の "ABC" "DEF"は両方メモリのある領域に確保されていて
    • +するとメモリ領域に"ABCDEF"は新しく別の領域に確保されてる
    • 確保しながら足していくというコストのかかるoutputになっている。。。
  • →StringBuilderクラスのappendメソッドを使うと、一定のサイズを確保した可変長の文字列を表すので、確保した領域で文字列を自由に変更できる
    • appendは何をしたいかのみ蓄えて最後一回のみ結合するということ
      • "ABC" "DEF" "GHI" 足したいものを蓄えて、最後一回のみ結合
      • "ABCDEFGHI"
  • →インスタンスの生成・破棄が少ない!
  • 最新のJavaでは+ 演算子は内部的にStringBuilderに変換されるので単発の文字列連結の場合+演算子でOK

時間比較

100000文字連結した結果、stringBuilderが7msで圧勝!

import java.util.Date;

public class Main {
    public static void main(String[] args) { new Main().run(); }
    private void run(){
        long startTime = getNow();
        String hoge = "";
        for (int i= 0; i < 100000; i++){
            hoge  = hoge + "mohu";
        }
        long elapse = getNow() - startTime;
        System.out.println("elapse "+ elapse ); //2716ms
    }
    //Dateで今の時間をとる
    private long getNow(){
        return new Date().getTime();
    }
}
import java.util.Date;

public class Main {
    public static void main(String[] args) { new Main().run(); }
    private void run(){
        long startTime = getNow();
         StringBuilder stringBuilder = new StringBuilder();
        for (int i= 0; i < 100000; i++){
            stringBuilder.append("mohu");
        }
        long elapse = getNow() - startTime;
        System.out.println("elapse "+ elapse ); //7ms
    }
    //Dateで今の時間をとる
    private long getNow(){
        return new Date().getTime();
    }
}

複数の Hello World の出力

1000 個の "Hello World" を出力するプログラムを作成して下さい。

  • 注意:AOJはJava9より下位JDKを使って動作しているので型推論varは動作しない(①)
    • 変数名(symbol) builderが定義されていないというコンパイルエラーになる
    • Aizu Online ではコンパイルエラーだと [CE]
//①AOJでは動かないが正しいコード
//cannot find symbol var builder = new StringBuilder();
public class Main{
    public static void main(String[] args){
        var builder = new StringBuilder();
        for (var i=0;  i<1000; i++){
            builder.append("Hello World\n");
        }
        var result = builder.toString();
        System.out.println(result);
    }
}

//②AOJで動きます
public class Main {

    public static final int BIG_NUM  = 2000000000;
    public static final int MOD  = 1000000007;

    public static void main(String[] args) {
        StringBuilder ans = new StringBuilder();
        for(int i = 0; i < 1000; i++){
            ans.append("Hello World\n");
        }
        System.out.print(ans.toString());
    }
}

BufferedReaderとScannerの違い

  • Scannerは遅いしメモリを食う問題。。。
  • 高速化が必要な場合はBufferedReader.readLineで行ごとに読み込む
  • 比較
    • BufferedReaderの方がScannerよりパフォーマンスが優れている
    • BufferedReaderは文字列しか受け取れないがScannerは数値も直接受け取れる
      • BufferedReader数値を扱いたい場合は、文字列を受け取ったあとに数値に変換
      • ScannerはnextInt()メソッドを使うことで数値を直接受け取れる
    • BufferedReaderはチェック例外の対処が必要(IOException)だが、Scannerは不要
      • BufferedReaderはチェック例外の対処(try-catch文など)が必要

テストケースの出力

オンラインジャッジでは、提出されたプログラムが複数の入力データそれぞれに対して正しい出力を行っているかを判定するために、1つの入力データファイルに複数のデータセットが含まれているものがあります。この問題は、そのようなデータセットを処理するための練習問題です。
1つの整数 x を読み込み、それをそのまま出力するプログラムを作成して下さい。
Output 各データセットごとに、以下の形式で x を出力して下さい:
Case i: x

//実行時間18s
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {
    public static void main(String[] args) throws NumberFormatException, IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int i=0;
        while(true){
            i++;
            int k = Integer.parseInt(br.readLine());
            if(k == 0){break;}
            System.out.println("Case "+i+": "+k);
        }
    }
}
//実行時間31s
import java.util.Scanner;
public class Main {
    public static void main(String[] args){
        Scanner in = new Scanner(System.in);
        for(int i=1;;i++){
            int num=in.nextInt();
            if(num==0)
                break;
            System.out.println("Case "+i+": "+num);
        }
    }
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0