きり丸の技術日記

技術検証したり、資格等をここに残していきます。

Javaで数値から1桁ずつの数値配列に変換する(109を1,0,9の配列に変換する)

小ネタ。業務で使ったことは無いですが、LeetCodeで必要になることが多いので自分向けに整理します。

なお、もっとよりよいやり方があれば教えていただきたいです。

環境

  • Java
    • 15

ゴール

  • 入力値は数値
  • 戻り値は数値の配列(Listでも配列でもOK)

最も早く変換できるやり方

タイトルの例とは順序が逆になりますが、早く変換できます。(109 -> 9, 0, 1)

数値だけ処理したいことが多いので、これがあれば大体十分です。

なお、ArrayListの初期配列を設定したほうが早いのですが、初期配列数を求めるためのコストが高いので今回はデフォルト値を設定しています。もし、問題文の中で最大長が提示されている場合は、最大長の桁数を設定してもいいでしょう。

処理速度は1000万回実行し、4227ミリ秒でした。

  public List<Integer> toArrayReverseOrder(int i) {

    List<Integer> list = new ArrayList<>();
    while (i != 0) { // 10で割った結果が0になったら終了する
      list.add(i % 10); // 1桁目を取得する
      i /= 10; // 1/10にする
    }

    return list;
  }

分かりやすいやり方

数値を文字列にして、1文字ずつ取り出しつつ、返却用の数値配列に設定します。

ただ、数値 <-> 文字列の変換コストが非常に重いです。

処理速度は1000万回実行し、8491ミリ秒でした。

  public List<Integer> toArray(int i) {

    List<Integer> list = new ArrayList<>();
    for (char c : String.valueOf(i).toCharArray()) { // 数値を文字列にしつつ、1文字ずつ取得
      list.add(Integer.parseInt(String.valueOf(c))); // char型を一旦Stringにし、その後Integerに変換する
    }

    return list;
  }

ワンライナーでやるやり方

処理の見た目はすごいシンプルです。

数値を文字列に変換し、chars()でIntStreamに変換します。0のchar型が48なので、マイナス48をすることで元の数値を取得することができます。

あとは、toArray()int[]を取得することができます。

処理速度は1000万回実行し、8359ミリ秒でした。

  public int[] toArray2(int i) {
    return String.valueOf(i).chars().map(e -> e - 48).toArray();
  }

ソースコード

実装コード https://github.com/hirotoKirimaru/cucumber-sample/blob/d77710a35b451c2179bff08bd012f5e4895894e4/src/main/java/kirimaru/biz/domain/NumToNumArray.java

テストコード https://github.com/hirotoKirimaru/cucumber-sample/blob/fc2f91fa909534078a8d6b36b65aee65953a349d/src/test/java/kirimaru/biz/domain/NumToNumArrayTest.java

終わりに

やっぱり型変換のコストは大きいですね。

気付いてはいましたが、ちゃんと計測したことが無かったので2倍くらい処理速度に差が出ることに気づけて良かったです。

正直、ロジック自体は簡単ですが、毎回忘れるのでメモとして残しておきます。