20201115のJavaに関する記事は17件です。

Javaのプリミティブ特殊化まとめ

前置き

Java SE8の関数型インタフェースやStreamのプリミティブ特殊化についてまとめました。
目的はJava Gold試験対策です。

プリミティブ特殊化とは

javaでは、Function<T,R>のR apply(T t) のT,Rのような型引数にはプリミティブを与えることができない。関数型インタフェースやStreamにおいては、int、long、doubleについても(ラッパークラスにボクシングせずに)ジェネリクスっぽく操作ができるように、個別にクラスがいくつか定義されている。これをプリミティブ特殊化を行った型という。
intだけ覚えておけばlong, doubleも差異は無い。

関数型インターフェイスの整理

java.util.functionの全関数型インタフェース

基本のクラス名 intへの特殊化 longへの特殊化 doubleへの特殊化 基本のメソッド名
Function<T,R> IntFunction<R> LongFunction<R> DoubleFunction<R> apply()
Function<T,R> IntToDoubleFunction LongToDoubleFunction DoubleToIntFunction apply()
Function<T,R> IntToLongFunction LongToIntFunction DoubleToLongFunction apply()
Function<T,R> ToIntFunction<T> ToLongFunction<T> ToDoubleFunction<T> apply()
UnaryOperator<T> IntUnaryOperator LongUnaryOperator DoubleUnaryOperator apply()
BiFunction<T,U,R> ToIntBiFunction<T,U> ToLongBiFunction<T,U> ToDoubleBiFunction<T,U> apply()
BinaryOperator<T> IntBinaryOperator LongBinaryOperator DoubleBinaryOperator apply()
Predicate<T> IntPredicate LongPredicate DoublePredicate test()
BiPredicate<T,U> - - - test()
Consumer<T> IntConsumer LongConsumer DoubleConsumer accept()
BiConsumer<T,U> ObjIntConsumer<T> ObjLongConsumer<T> ObjDoubleConsumer<T> accept()
Supplier<T> IntSupplier LongSupplier DoubleSupplier get()
BooleanSupplier - - - getAsBoolean()


ポイント

  • プリミティブ特殊化された関数型インタフェースは、プリミティブ特殊化されたStreamのメソッドの引数として現れる。

  • 関数型インタフェースのメソッド名は、戻り値がプリミティブの場合にだけ、 「基本のメソッド名As型名」 とする。

    • e.g.
    • R apply(T t) →戻り値をintに→ int applyAsInt(T t)
    • T get() →戻り値をdoubleに→ double getAsDouble()
  • 特殊化の対象は基本的にint, long, doubleのみで、BooleanSupplierは特別。

    • BooleanSupplierはたぶんテストやアサーションを書くときに使う想定なのかな。
    • 「悪いなfloat、このパッケージは3人用なんだ」
  • Functionのプリミティブ特殊化は、次の各パターンに対応している。

    • プリミティブの引数をとってプリミティブを返す
    • オブジェクトの引数をとってプリミティブを返す
    • プリミティブの引数をとってオブジェクトを返す
    • 表の2,3行目で、IntToIntFunctionはないの?となりそうだが、それはIntUnaryOperator。
  • BiConsumerに対応するObjIntConsumerのaccept()は、引数1がオブジェクトで引数2がintとなっている。
    これはIntStream.collect()のアキュムレータとして使う。

java.util.streamのプリミティブ特殊化の整理

種類

Stream<T>からプリミティブ特殊化された型は以下の3クラス。

  • IntStream
  • LongStream
  • DoubleStream

ここでは仮にプリミティブ特殊化ストリームと呼ぶことにします。

プリミティブ特殊化ストリーム特有の終端操作

  • sum() : 和をとる。
  • avarage() : 算術平均をとる。戻り値はOptionalDouble。
  • max() : 順序が自明なので、Stream<T>.max(Comparator)と異なり引数を取らない。
  • min() : 順序が自明なので、Stream<T>.min(Comparator)と異なり引数を取らない。

Stream<T>とプリミティブ特殊化ストリームの相互変換

プリミティブ特殊化ストリームから

mapToXxx()メソッド

this 戻り値 メソッド名 引数
IntStream LongStream mapToLong *1 IntToLongFunction
IntStream DoubleStream mapToDouble *1 IntToDoubleFunction
IntStream Stream<T> mapToObj *2 IntFunction<? extends T>
LongStream IntStream mapToInt LongToIntFunction
LongStream DoubleStream mapToDouble *1 LongToDoubleFunction
LongStream Stream<T> mapToObj *2 LongFunction<? extends T>
DoubleStream IntStream mapToInt DoubleToIntFunction
DoubleStream LongStream mapToLong DoubleToLongFunction
DoubleStream Stream<T> mapToObj *2 DoubleFunction<? extends T>


*1 単なるアップキャストは、asXxx()メソッドでできる

this 戻り値 メソッド名 引数
IntStream DoubleStream asDoubleStream -
IntStream LongStream asLongStream -
LongStream DoubleStream asDoubleStream -


*2 単なるボクシングは、boxed()メソッドでできる

this 戻り値 メソッド名 引数
IntStream Stream<Integer> boxed -
LongStream Stream<Long> boxed -
DoubleStream Stream<Double> boxed -


Stream<T>からプリミティブ特殊化ストリームへ

mapToXxx()メソッド

this 戻り値 メソッド名 引数
Stream<T> IntStream() mapToInt ToIntFunction<? super T>
Stream<T> LongStream() mapToLong ToLongFunction<? super T>
Stream<T> DoubleStream() mapToDouble ToDoubleFunction<? super T>


flatMapToXxx()メソッド

平坦化とプリミティブ特殊化の組み合わせ。いかにも試験に出そうなやつ

this 戻り値 メソッド名 引数
Stream<T> IntStream() flatMapToInt Function<? super T,? extends IntStream>
Stream<T> LongStream() flatMapToLong Function<? super T,? extends LongStream>
Stream<T> DoubleStream() flatMapToDouble Function<? super T,? extends DoubleStream>



追加すべきものがあったら教えてください。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

配列変数 と 連想配列 初学者が初学者向けにまとめた

どうも。
今まで掲示板等々を学習がてら作成してきましたが、5ヶ月というスパンで焦り走りしてきた事で
「フワッとした理解」で「〇〇機能は〇〇で実装できるだろう」と何となく分かるものの、Google先生の力がなければこれ一つ自分で実装できない僕が、
一つ一つの細かな理解が疎かであることから、
これから基礎の基礎を深く理解するためにアウトプットの場としてQiitaに投稿していきます。

自身でGoogle先生を活用して数十サイトや書籍を参考に理解を深めながら、
1、、実際にコードを書いて
2、、ノートに自分の言葉でいつかの自分が見ても伝わるようにまとめていく
3、、最後にQiitaに他の方が見ても分かるよう伝えていく

※間違い部分、誤解している箇所が出てくる可能性もあります。

[配列とは]

複数(プロパティ)のデータをまとめて整理して1つの大きな箱にいれるイメージ。
333.png
出力結果:アイス

呼び方まとめ

・青box1つ1つのまとまりをプロパティと呼ぶ。

・ここでは$box全ての部分を【配列】と呼ぶ。

・自動的に割り当てられる添字のことを【キー】と呼ぶ。

・アイス、チョコアイス、カレー味アイスの部分を【値】と呼ぶ。

問題

ee.png

正解はスクロールしたらすぐ出てきますので、ここから下にスクロールせず解答してみること。

正解:2.3.4.1

※プロパティを要素、配列をインデックスとも呼ぶ。

問題2

Hamburger 配列変数に
テリヤキバーガー/ベーコンレタスバーガー/ホットケーキ
上記3つのハンバーガー[]を上記の順番に格納すること
最後にテリヤキバーガーを出力結果に表示してください

先ずは自身でやること。
答えは以下のリンクを押すと出てきます。
https://paiza.io/projects/pik0u6YBKOv40ZuMP-pG6g

次に、$Hamburger配列変数からテリヤキバーガーとホットケーキを改行して出力結果に表示してください。
https://paiza.io/projects/pik0u6YBKOv40ZuMP-pG6g

改行の仕方は複数通りあるため上記URLの方法以外でも改行して出力出来ていればOK!!

ちなみに、上記URLの通りに文字列の中に変数を取り入れる場合は""(ダブルクォーテーション)です。
ダブルクォーテーションとシングルクォーテーションの違いは以下URLが非常に分かりやすいです!
https://qiita.com/bitcoinjpnnet/items/64458299eaeefbacab44

配列に格納されている値を全て出力結果に表示するには?

foreach文を使います。

【foreach文とは】
(リスト)や(配列)に格納されたデータ[要素とも値とも呼ぶ]に対して記述[プログラム]された処理を
繰り返し実行する力を持っているループ文です。

$box = ['アイス','チョコアイス','カレー味アイス'];
foreach($box as $value) {
    echo $value;
}
出力結果:アイスチョコアイスカレー味アイス

格納されたデータが全て出力されると繰り返し終了します。

また、添字[キー]も出力したい場合には

foreach ($box as $key=>$value){
echo "$key=>$value \n";
}

出力結果:
0=>アイス
1=>チョコアイス
2=>カレー味アイス

おさらいです。
文字列の中で変数展開したい場合はダブルクォーテーションで囲む。
\nは改行を意味します。
Macユーザーの方は半角[optionキー+¥]。

$valueの部分は任意名です。

問題3

Hamburger配列変数に格納されてる値を全て出力結果に表示してください。

答え
https://paiza.io/projects/pik0u6YBKOv40ZuMP-pG6g

Hamburger配列変数に格納されている値とキーを全て出力結果に表示してください。
条件
改行を行うこと。
カンマ/コンマをいれること

表示結果例
キー=>値、
キー=>値、
キー=>値、

答え
https://paiza.io/projects/pik0u6YBKOv40ZuMP-pG6g

但し、やり方は複数通りある。

これである程度配列についての理解が出来たのではないでしょうか?
配列を初めて聞いた方は少しまだ理解できていないかもしれません。
Google先生に「配列 とは」で検索すると結構出てきます。

それでは次に連想配列について理解を深めていきたいと思います。

連想配列とは

任意の文字列をキーに割り当てる事が可能。
・文字列(クォーテーションで囲むもの)
・整数

連想配列の良いところ

・キーが任意文字列のため値と同じ意味を持たせた文字列にすればパッと見て分かりやすい!
例: Apple =>りんご car => 車

・1つの小箱(要素ともいうプロパティともいう)にキーと値で2つの意味を持たせれる。
例: 顧客の連絡先と名前を管理したい場合
例: '〇〇会社小林様' => xxx-xxxx-xxxx(これは電話番号です)

実際に試して覚えよう!

連想配列のキーに割り当てられるが注意すべき事

・true false ・・・ キーに割り当てれるが、true = 1 false = 0に自動変換される
・小数点       ・・・ キーに割り当てれるが、自動的に切り捨て整数に自動変換される


実際に試して覚えよう!
https://paiza.io/projects/pik0u6YBKOv40ZuMP-pG6g

連想配列もつまりは配列の仲間なので配列を理解出来れば連想配列も理解できると思います。

次回、配列を複数の出力方法で出力をし、ループ処理等を併せて理解する記事を書きます。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Java】暗黙的型キャスト(AOJ⑨数字の和)

型キャスト

public class Main {
    public static void main(String[] args)  {

        char c = '1';
        //暗黙的にint型、double型にキャスト
        int i = c;
        double d = c;
        System.out.println(c + "をint型へキャスト→ " + i);
        System.out.println(c + "をdouble型へキャスト→ " + d);

        //引数がdouble型のメソッドに、char型を引数として渡す
        doubleMethod(c);
    }

    static void doubleMethod(double d) {
        System.out.println("double型→ " + d);
    }
}
1をint型へキャスト 49
1をdouble型へキャスト 49.0
double型 49.0

数字の和(ITP1-8)

与えられた数の各桁の和を計算するプログラムを作成して下さい。
Input
複数のデータセットが入力として与えられます。各データセットは1つの整数 x を含む1行で与えられます。
x は 1000 桁以下の整数です。
x が 0 のとき入力の終わりとします。このデータセットに対する出力を行ってはいけません。
Output
各データセットに対して、x の各桁の和を1行に出力して下さい。

  • この例でのans += line.charAt(i)-‘0’;で暗黙的にキャストをしている
    • line.charAt(i)はcharを返す
    • ansはintegerなので、integerに変換する
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int ans;

        while(true){
        String line = br.readLine();
            if(line.length() == 1 && line.equals("0")){
                break;
            }else{
                ans= 0;
                for(int i = 0; i < line.length(); i++){
                    ans += line.charAt(i)-'0';

               /*型キャストの確認
               System.out.println("line.charAt(i) "+line.charAt(i));
               System.out.println("line[i] "+(int)line.charAt(i));
               System.out.println("(int)'0' "+(int)'0');
               */
               }
               System.out.println(ans);

            }
        }
    }
}  
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Java】暗黙的型キャスト(AOJ10 - 数字の和)

型キャスト

public class Main {
    public static void main(String[] args)  {

        char c = '1';
        //暗黙的にint型、double型にキャスト
        int i = c;
        double d = c;
        System.out.println(c + "をint型へキャスト→ " + i);
        System.out.println(c + "をdouble型へキャスト→ " + d);

        //引数がdouble型のメソッドに、char型を引数として渡す
        doubleMethod(c);
    }

    static void doubleMethod(double d) {
        System.out.println("double型→ " + d);
    }
}
1をint型へキャスト 49
1をdouble型へキャスト 49.0
double型 49.0

数字の和(ITP1-8)

与えられた数の各桁の和を計算するプログラムを作成して下さい。
Input
複数のデータセットが入力として与えられます。各データセットは1つの整数 x を含む1行で与えられます。
x は 1000 桁以下の整数です。
x が 0 のとき入力の終わりとします。このデータセットに対する出力を行ってはいけません。
Output
各データセットに対して、x の各桁の和を1行に出力して下さい。

  • この例でのans += line.charAt(i)-‘0’;で暗黙的にキャストをしている
    • line.charAt(i)はcharを返す
    • ansはintegerなので、integerに変換する
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int ans;

        while(true){
        String line = br.readLine();
            if(line.length() == 1 && line.equals("0")){
                break;
            }else{
                ans= 0;
                for(int i = 0; i < line.length(); i++){
                    ans += line.charAt(i)-'0';

               /*型キャストの確認
               System.out.println("line.charAt(i) "+line.charAt(i));
               System.out.println("line[i] "+(int)line.charAt(i));
               System.out.println("(int)'0' "+(int)'0');
               */
               }
               System.out.println(ans);

            }
        }
    }
}  
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Java】文字列を大文字/小文字へ変換(AOJ⑧)

大文字/小文字の変換

  • 文字列を大文字/小文字へ変換
    • toUpperCase, toLowerCaseメソッド
  • 大文字/小文字かどうかを判別
    • isUpperCase. isLowerCaseメソッド
public class Main {
    public static void main(String[] args){
    String str1 = new String("MoHuNeKo");
    String upper_str1 = str1.toUpperCase();
    String lower_str1 = str1.toLowerCase();

    System.out.println("入力文字列 : " + str1);
    System.out.println("1文字目は大文字? : " + Character.isUpperCase(str1.charAt(0)));
    System.out.println("大文字変換 : " + upper_str1);
    System.out.println("小文字変換 : " + lower_str1);
    System.out.println("=======^・ω・^=======");

    String str2 = new String("The current world population is about 7,594,690,000!");
    String upper_str2 = str2.toUpperCase();
    String lower_str2 = str2.toLowerCase();

    System.out.println("入力文字列 : " + str2);
    System.out.println("2文字目は小文字? : " + Character.isLowerCase(str2.charAt(1)));
    System.out.println("大文字変換 : " + upper_str2);
    System.out.println("小文字変換 : " + lower_str2);
    System.out.println("==============");
    System.out.println("大文字? : " + Character.isUpperCase('\n'));
    System.out.println("小文字? : " +Character.isLowerCase('\t'));
   }
}
入力文字列 : MoHuNeKo
1文字目は大文字? : true
大文字変換 : MOHUNEKO
小文字変換 : mohuneko
=======^ω^=======
入力文字列 : The current world population is about 7,594,690,000!
2文字目は小文字? : true
大文字変換 : THE CURRENT WORLD POPULATION IS ABOUT 7,594,690,000!
小文字変換 : the current world population is about 7,594,690,000!
==============
大文字? : false
小文字? : false

大文字と小文字の入れ替え(ITP1-8)

与えられた文字列の小文字と大文字を入れ替えるプログラムを作成してください。
Input
文字列が1行に与えられます。
Output
与えられた文字列の小文字と大文字を入れ替えた文字列を出力して下さい。アルファベット以外の文字はそのまま出力して下さい。
Constraints
* 入力される文字列の長さ < 1200
Sample Input
fAIR, LATER, OCCASIONALLY CLOUDY.
Sample Output
Fair, later, occasionally cloudy.

import java.util.Scanner;

public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        String line = sc.nextLine();
        StringBuilder sb = new StringBuilder();

        for(int i = 0; i < line.length() ; i++){
            char now = line.charAt(i);
            if(Character.isUpperCase(now))      sb.append(Character.toLowerCase(now));
            else if(Character.isLowerCase(now)) sb.append(Character.toUpperCase(now));
            else                                sb.append(now);
        }
        System.out.println(sb);
    }
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Java】文字列を大文字/小文字へ変換(AOJ⑨ - 大文字と小文字の入れ替え)

大文字/小文字の変換

  • 文字列を大文字/小文字へ変換
    • toUpperCase, toLowerCaseメソッド
  • 大文字/小文字かどうかを判別
    • isUpperCase. isLowerCaseメソッド
public class Main {
    public static void main(String[] args){
    String str1 = new String("MoHuNeKo");
    String upper_str1 = str1.toUpperCase();
    String lower_str1 = str1.toLowerCase();

    System.out.println("入力文字列 : " + str1);
    System.out.println("1文字目は大文字? : " + Character.isUpperCase(str1.charAt(0)));
    System.out.println("大文字変換 : " + upper_str1);
    System.out.println("小文字変換 : " + lower_str1);
    System.out.println("=======^・ω・^=======");

    String str2 = new String("The current world population is about 7,594,690,000!");
    String upper_str2 = str2.toUpperCase();
    String lower_str2 = str2.toLowerCase();

    System.out.println("入力文字列 : " + str2);
    System.out.println("2文字目は小文字? : " + Character.isLowerCase(str2.charAt(1)));
    System.out.println("大文字変換 : " + upper_str2);
    System.out.println("小文字変換 : " + lower_str2);
    System.out.println("==============");
    System.out.println("大文字? : " + Character.isUpperCase('\n'));
    System.out.println("小文字? : " +Character.isLowerCase('\t'));
   }
}
入力文字列 : MoHuNeKo
1文字目は大文字? : true
大文字変換 : MOHUNEKO
小文字変換 : mohuneko
=======^ω^=======
入力文字列 : The current world population is about 7,594,690,000!
2文字目は小文字? : true
大文字変換 : THE CURRENT WORLD POPULATION IS ABOUT 7,594,690,000!
小文字変換 : the current world population is about 7,594,690,000!
==============
大文字? : false
小文字? : false

大文字と小文字の入れ替え(ITP1-8)

与えられた文字列の小文字と大文字を入れ替えるプログラムを作成してください。
Input
文字列が1行に与えられます。
Output
与えられた文字列の小文字と大文字を入れ替えた文字列を出力して下さい。アルファベット以外の文字はそのまま出力して下さい。
Constraints
* 入力される文字列の長さ < 1200
Sample Input
fAIR, LATER, OCCASIONALLY CLOUDY.
Sample Output
Fair, later, occasionally cloudy.

import java.util.Scanner;

public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        String line = sc.nextLine();
        StringBuilder sb = new StringBuilder();

        for(int i = 0; i < line.length() ; i++){
            char now = line.charAt(i);
            if(Character.isUpperCase(now))      sb.append(Character.toLowerCase(now));
            else if(Character.isLowerCase(now)) sb.append(Character.toUpperCase(now));
            else                                sb.append(now);
        }
        System.out.println(sb);
    }
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Spring Framework]Configurationの分割

Configurationの分割

肥大化したJava Configを分割する方法です。

Java Configの分割

メインクラス

分割したサブクラスを@org.springframework.context.annotation.Importで読み込む。

AppConfig.java
@Configuration
@Import({SubConfig.class, Sub2Config.class})
public class AppConfig {
  // subConfig.class, sub2Config.classに定義したBeanがインジェクションされる
}

分割したサブクラス

@Configurationをつける

SubConfig.java
@Configuration
public class SubConfig {
  @Bean
  UserService userService() {
  // ・・・
  }
}
Sub2Config.java
@Configuration
public class Sub2Config {
  @Bean
  ShopService shopService() {
  // ・・・
  }
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Java】多次元配列・内積計算(AOJ⑦内積)

多次元配列

// 3*4*5の三次元配列
init [][][] list = new int [3][4][5]; 
// 2次元配列を初期化して宣言
int [][] list = [
  { 1, 2, 3 },
  { 4, 5, 6 },
  { 7, 8, 9 },
};
//var で初期化して宣言
var list = new int[][] [
  { 1, 2, 3 },
  { 4, 5, 6 },
  { 7, 8, 9 },
};
// 0行1列目にアクセス
System.out.println(list[0][1]); //2

ジャグ配列

  • 長さが異なる多次元配列
  • 最初の宣言では外側のサイズのみ指定
  • 1次元目は確保しないといけないが2次元目は確保不要
  • 2次元以降はダイナミックに変更できる!
    • ユースケース
    • 全人口の給料の配列を作るときに都道府県ごとに作成
    • int [][] = salary = new int[47][];
var list = new int [3][];
list[0] = new int[2]; //0番目の配列の要素は2個
list[1] = new int[3]; //0番目の配列の要素は3個
list[2] = new int[4]; //0番目の配列の要素は4個
var list = new int [][] {
  { 1, 2 },
  { 3, 4, 5 },
  { 6, 7, 8, 9 },
};
System.out.println(list[1][2]); //5 ※サイズは3

公舎の入居者数

A大学は1フロア10部屋、3階建ての公舎4棟を管理しています。公舎の入居・退去の情報を読み込み、各部屋の入居者数を出力するプログラムを作成して下さい。
n件の情報が与えられます。各情報では、4つの整数b, f, r, vが与えられます。これは、b棟f階のr番目の部屋にv人が追加で入居したことを示します。vが負の値の場合、-v人退去したことを示します。
最初、全ての部屋には誰も入居していないものとします。
Input
最初の行に情報の数 n が与えられます。
続いて n 件の情報が与えられます。各情報には4つの整数 b, f, r, v が空白区切りで1行に与えられます。
Output
4棟について入居者数を出力して下さい。各棟について、1階、2階、3階の順に入居者数を出力します。各階については、1番目、2番目、・・・、10番目の部屋の入居者数を順番に出力します。入居者数の前には1つの空白を出力して下さい。また、各棟の間には####################(20個の#)で区切って下さい。
Constraints
* 間違った棟番号・階・部屋番号は与えられない。
* 管理の過程で1部屋の入居者数が0より少なくなることはない。
* 管理の過程で1部屋の入居者数が9より多くなることはない。

import java.util.Scanner;
public class Main {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        //10部屋、3階建ての公舎4棟
        int[][][] list = new int[4][3][10];

        for(int i = 0; i < n; i++) {
            //b棟f階のr番目の部屋にv人が追加
            int b = sc.nextInt();
            int f = sc.nextInt();
            int r = sc.nextInt();
            int v = sc.nextInt();

            list[b-1][f-1][r-1] += v;
        }

        for(int i = 0 ; i< 4; i++) {
            for(int j = 0; j < 3; j++) {
                for (int k = 0; k < 10; k++) {
                    System.out.print(" " + list[i][j][k]);
                }
                System.out.println();
            }
            if (i != 3)
                System.out.println("####################");
        }
        }
}

ベクトルと行列の積

Input
1行目に n と mが空白区切りで与えられます。続く 
n 行に行列 A の要素aij が空白区切りで与えられます。続く m 行にベクトルbの要素 bi がそれぞれ1行に与えられます。
Output
出力は n行からなります。ベクトル cの要素 ci をそれぞれ1行に出力してください

//内積計算
import java.util.Scanner;

public class Main {
    public static void main(String[] args){
        Scanner scan=new Scanner(System.in);
        int n=scan.nextInt();
        int m=scan.nextInt();
        int a[][]=new int[n][m];
        //行列A
        for(int i=0;i<n;i++)for(int j=0;j<m;j++){
            a[i][j]=scan.nextInt();
        }
        //ベクトルb
        int b[]=new int[m];
        for(int i=0;i<m;i++)b[i]=scan.nextInt();
        //ベクトルc
        int c[]=new int[n];
        //c=A*b 内積計算
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                c[i]+=a[i][j]*b[j];
            }
        }
        for(int i=0;i<n;i++)System.out.println(c[i]);
        scan.close();
    }
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Java】データ型・行列の積(AOJ⑦行列の積)

データ型(データの種類)

  • データの種類と大きさにあったデータ型を使う
    • byte, char:バイトデータを格納する
    • short:小さな整数を表す
    • long:intで対応できない数値範囲を扱う場合のみ
  • 参考: 【Java】データ型①-基本型
public class Main {
    public static void main(String[] args){
        //int型の最小値と最大値を確認する
        System.out.println("int   最小/最大値= " + Integer.MIN_VALUE+" ~ "+Integer.MAX_VALUE);
        System.out.println("byte  最小/最大値= " + Byte.MIN_VALUE+" ~ "+Byte.MAX_VALUE);
        System.out.println("short 最小/最大値= " + Short.MIN_VALUE+" ~ "+Short.MAX_VALUE);
        System.out.println("long  最小/最大値= " + Long.MIN_VALUE+" ~ "+Long.MAX_VALUE);
    }
}
int   最小/最大値= -2147483648 ~ 2147483647
byte  最小/最大値= -128 ~ 127
short 最小/最大値= -32768 ~ 32767
long  最小/最大値= -9223372036854775808 ~ 9223372036854775807

行列の積(ITP1-7)

n×m の行列 Aと m×l の行列 B を入力し、それらの積である n×l の行列 C を出力するプログラムを作成してください。
ここで、A、B、C の各要素をそれぞれ aij、bij、cij とします。
Input
1行目に n、m、l が空白区切りで与えられます。
続く行に n×m の行列 A と m×l の行列 B が与えられます。
Output
n×l の行列 Cの要素 cijを出力してください。各行の隣り合う要素を1つの空白で区切ってください。
Constraints
* 1≤n,m,l≤100
* 0≤aij,bij≤10000


//内積計算
import java.util.Scanner;
import java.util.Arrays;
public class Main {
    public static void main(String[] args){
        Scanner scan=new Scanner(System.in);
        int n=scan.nextInt();
        int m=scan.nextInt();
        int l=scan.nextInt();

        //0≤aij,bij≤10000なので
        //int型の最大範囲2147483647に入らない場合があるので注意!
        // int[][] a=new int[n][m];
        // int[][] b=new int[m][l];
        // int[][] c=new int[n][l];

        long[][] a = new long[n][m];
        long[][] b = new long[m][l];
        long[][] c = new long[n][l];

        //行列A
        for(int i=0;i<n;i++)for(int j=0;j<m;j++){
            a[i][j]=scan.nextInt();
        }

        //行列B
        for(int i=0;i<m;i++)for(int j=0;j<l;j++){
            b[i][j]=scan.nextInt();
        }

        //行列の積 c=a*b
        for(int i=0;i<n;i++){
            for(int j=0;j<l;j++){
                for(int k=0;k<m;k++){
                    c[i][j]+=a[i][k]*b[k][j];
                }
            }
        }
        // System.out.println(Arrays.deepToString(c));
        StringBuilder sb = new StringBuilder();
        for(int i=0;i<n;i++){
            for(int j=0;j<l;j++){
                sb.append(c[i][j]);
                if(j != l-1) sb.append(" ");
            }
            if(i != n-1) sb.append("\n");
        }
        System.out.println(sb);
        scan.close();
    }
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Java】データ型・行列の積(AOJ⑧行列の積)

データ型(データの種類)

  • データの種類と大きさにあったデータ型を使う
    • byte, char:バイトデータを格納する
    • short:小さな整数を表す
    • long:intで対応できない数値範囲を扱う場合のみ
  • 参考: 【Java】データ型①-基本型
public class Main {
    public static void main(String[] args){
        //int型の最小値と最大値を確認する
        System.out.println("int   最小/最大値= " + Integer.MIN_VALUE+" ~ "+Integer.MAX_VALUE);
        System.out.println("byte  最小/最大値= " + Byte.MIN_VALUE+" ~ "+Byte.MAX_VALUE);
        System.out.println("short 最小/最大値= " + Short.MIN_VALUE+" ~ "+Short.MAX_VALUE);
        System.out.println("long  最小/最大値= " + Long.MIN_VALUE+" ~ "+Long.MAX_VALUE);
    }
}
int   最小/最大値= -2147483648 ~ 2147483647
byte  最小/最大値= -128 ~ 127
short 最小/最大値= -32768 ~ 32767
long  最小/最大値= -9223372036854775808 ~ 9223372036854775807

行列の積(ITP1-7)

n×m の行列 Aと m×l の行列 B を入力し、それらの積である n×l の行列 C を出力するプログラムを作成してください。
ここで、A、B、C の各要素をそれぞれ aij、bij、cij とします。
Input
1行目に n、m、l が空白区切りで与えられます。
続く行に n×m の行列 A と m×l の行列 B が与えられます。
Output
n×l の行列 Cの要素 cijを出力してください。各行の隣り合う要素を1つの空白で区切ってください。
Constraints
* 1≤n,m,l≤100
* 0≤aij,bij≤10000


//内積計算
import java.util.Scanner;
import java.util.Arrays;
public class Main {
    public static void main(String[] args){
        Scanner scan=new Scanner(System.in);
        int n=scan.nextInt();
        int m=scan.nextInt();
        int l=scan.nextInt();

        //0≤aij,bij≤10000なので
        //int型の最大範囲2147483647に入らない場合があるので注意!
        // int[][] a=new int[n][m];
        // int[][] b=new int[m][l];
        // int[][] c=new int[n][l];

        long[][] a = new long[n][m];
        long[][] b = new long[m][l];
        long[][] c = new long[n][l];

        //行列A
        for(int i=0;i<n;i++)for(int j=0;j<m;j++){
            a[i][j]=scan.nextInt();
        }

        //行列B
        for(int i=0;i<m;i++)for(int j=0;j<l;j++){
            b[i][j]=scan.nextInt();
        }

        //行列の積 c=a*b
        for(int i=0;i<n;i++){
            for(int j=0;j<l;j++){
                for(int k=0;k<m;k++){
                    c[i][j]+=a[i][k]*b[k][j];
                }
            }
        }
        // System.out.println(Arrays.deepToString(c));
        StringBuilder sb = new StringBuilder();
        for(int i=0;i<n;i++){
            for(int j=0;j<l;j++){
                sb.append(c[i][j]);
                if(j != l-1) sb.append(" ");
            }
            if(i != n-1) sb.append("\n");
        }
        System.out.println(sb);
        scan.close();
    }
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

SpringBootことはじめ 0.SpringCLIを使う

はじめに

職場でSpring(Framework)を使うことになったので
前々から興味のあったSpringBootを触ってみることにした。
ちなみに SpringBoot≠SpringFramework だけどプライベートではあえてSpringBootを選択。

今回は、SpringBootの前にSpringCLIでお試し。

環境

ソフトウェア バージョン
OS Windows10 Pro
Java OpneJDK 12.0.2
Spring CLI v2.3.5.RELEASE

実施

1. SpringCLIを落とす。

公式入門ドキュメント(日本語)に記載してあるspring-boot-cli-2.3.5.RELEASE-bin.zipを落として解凍。
解凍後のフォルダ配下のspring-2.3.5.RELEASE\binフォルダをパスに通す。

これでspringコマンドが使えるようになる。
試しに以下のコマンドを実行してバージョンが返ってきたらインストール成功。

バージョン確認コマンド
spring version
実行結果
C:\>spring version
Spring CLI v2.3.5.RELEASE

2. REST API用コード実装

PC上のどこでもいいのでREST API用のコードを書く。
公式入門ドキュメントではGroovyで書いているが、Javaでもいい。

【Java】app.java
@RestController
public class Test {

    @RequestMapping("/")
    public String home() {
        return "Hello World!";
    }

    @RequestMapping("/sb")
    public String helloSb() {
        return "Hello SpringBoot!";
    }

}
【Groovy】app.groovy
@RestController
class ThisWillActuallyRun {

    @RequestMapping("/")
    String home() {
        "Hello World!"
    }

    @RequestMapping("/sb")
    String helloSb() {
        "Hello SpringBoot!"
    }

}

ちなみに上記程度ならimport文は不要。(IDEでやるとコンパイルエラー表示出るけど)

3. 実行

REST API用ソースコードがある場所で以下のコマンドを実行。

spring run app.java

すると以下のメッセージが表示されてREST APIアプリケーションが起動する。
必要なライブラリは自動的にDLされている模様。

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.3.5.RELEASE)

2020-11-15 12:31:05.416  INFO 9532 --- [       runner-0] o.s.boot.SpringApplication               : Starting application on XXXXXXXXXX(マシン名) with PID 9532 (started by xxxx in M:\develop\works\Spring\20201115_springboot_start)
2020-11-15 12:31:05.421  INFO 9532 --- [       runner-0] o.s.boot.SpringApplication               : No active profile set, falling back to default profiles: default
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.codehaus.groovy.reflection.CachedClass (jar:file:/M:/develop/tools/Spring/spring-boot-cli-2.3.5.RELEASE-bin/spring-2.3.5.RELEASE/lib/spring-boot-cli-2.3.5.RELEASE.jar!/BOOT-INF/lib/groovy-2.5.13.jar!/) to method java.lang.Object.finalize()
WARNING: Please consider reporting this to the maintainers of org.codehaus.groovy.reflection.CachedClass
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
2020-11-15 12:31:06.384  INFO 9532 --- [       runner-0] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2020-11-15 12:31:06.394  INFO 9532 --- [       runner-0] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2020-11-15 12:31:06.394  INFO 9532 --- [       runner-0] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.39]
2020-11-15 12:31:06.426  INFO 9532 --- [       runner-0] org.apache.catalina.loader.WebappLoader  : Unknown class loader [org.springframework.boot.cli.compiler.ExtendedGroovyClassLoader$DefaultScopeParentClassLoader@6adca536] of class [class org.springframework.boot.cli.compiler.ExtendedGroovyClassLoader$DefaultScopeParentClassLoader]
2020-11-15 12:31:06.458  INFO 9532 --- [       runner-0] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2020-11-15 12:31:06.458  INFO 9532 --- [       runner-0] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 889 ms
2020-11-15 12:31:06.601  INFO 9532 --- [       runner-0] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2020-11-15 12:31:06.879  INFO 9532 --- [       runner-0] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2020-11-15 12:31:06.887  INFO 9532 --- [       runner-0] o.s.boot.SpringApplication               : Started application in 1.795 seconds (JVM running for 3.034)

4. 稼働確認

以下にアクセスしてみる。

http://localhost:8080/
image.png

http://localhost:8080/sb
image.png

おぉ~いいっスね~:grinning:

まとめ

SpringCLIだけで速攻でREST APIができてしまった。(文字列返すだけだけど)
この時点ならIDEすら不要。
めちゃくちゃ簡単なAPIモック作るならこれでもいいかもしれない。

次回はSpringBootのちゃんとした?アプリケーションを作りたい。

参考

公式入門ドキュメント(日本語)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Java】多次元配列を出力・表計算(AOJ⑥表計算)

StringBuilderで文字列表現を返す

  • StringBuilderで出力する時に気をつけないと以下のエラーに。。
    cannot convert from StringBuilder to String
  • StringBuilderで連結結果をコンソール出力のみなら、printlnメソッドが引数に指定された任意のオブジェクトに対してString.valueOfからのsb.toStringを呼び出す
    • println は引数が文字列でなかったときに toString を呼び出してくれてた
StringBuilder sb = new StringBuilder();
System.out.println(sb);
  • Stringとして結果を得る必要があるならtoStringを明示的に呼び出す
  • StringBuilderのtoStringメソッド
    • 新しいStringオブジェクトを割り当て、初期化し、このオブジェクトの現在の文字列を返す
StringBuilder sb = new StringBuilder();
String result = sb.toString();//OK
String result = sb;  //コンパイルエラー(型が違う)
参考

多次元配列を出力

  • 1次元の配列ではお馴染みArrays.toString
  • 多次元の配列ではArrays.deepToString
import java.util.*;
import java.util.Arrays;
public class Main {
    public static void main(String[] args) throws Exception {
        // 1次元配列
        int[] nums = new int[] { 1, 2, 3 };
        System.out.println(nums);//[I@36baf30c
        System.out.println(Arrays.toString(nums));// [1, 2, 3]
        // 多次元配列
        int[][] nums2 = new int[][] { { 1, 2, 3 }, { 11, 12, 13 } };
        System.out.println(nums2);// [[I@7a81197d
        System.out.println(Arrays.toString(nums2));// [[I@5ca881b5, [I@24d46ca6]

        System.out.println(Arrays.deepToString(nums2));// [[1, 2, 3], [11, 12, 13]]
    }
}

表計算(ITP1-7)

表計算を行う簡単なプログラムを作成します。
表の行数rと列数c、r × c の要素を持つ表を読み込んで、各行と列の合計を挿入した新しい表を出力するプログラムを作成して下さい。
【Input】
最初の行にrとcが空白区切りで与えられます。続くr行にそれぞれc個の整数が空白区切りで与えられます。
【Output】
(r+1) × (c+1) の新しい表を出力して下さい。各行の隣り合う整数は1つの空白で区切って下さい。各行の最後の列としてその行の合計値を、各列の最後の行としてその列の合計値を、最後の行・列に表全体の合計値を挿入して下さい。
【Constraints】
* 1 ≤ r, c ≤ 100
* 0 ≤ 要素 ≤ 100
【入力例】
4 5
1 1 3 4 5
2 2 2 4 5
3 3 0 1 1
2 3 4 4 6
【出力例】
1 1 3 4 5 14
2 2 2 4 5 15
3 3 0 1 1 8
2 3 4 4 6 19
8 9 9 13 17 56

import java.util.Scanner;
import java.util.Arrays;
class Main {
    Scanner sc = new Scanner(System.in);

    public void run() {
        int r = sc.nextInt(), c = sc.nextInt();

        int[][] A = new int[r + 1][c + 1];

        //r × c の要素を持つ表をスキャン
        for (int i = 0; i < r; i++)
            for (int j = 0; j < c; j++) {
                A[i][j] = sc.nextInt();
            }
        //列ごとの合計を計算しc列目に代入
        for (int i = 0; i < r; i++) {
            int sum = 0;
            for (int j = 0; j < c; j++) {
                sum += A[i][j];
            }
            A[i][c] = sum;
        }
        //行ごとの合計を計算しc列目に代入
        for (int j = 0; j <= c; j++) {
            int sum = 0;
            for (int i = 0; i < r; i++) {
                sum += A[i][j];
            }
            A[r][j] = sum;
        }
        //中身確認
        //System.out.println(Arrays.deepToString(A));

        //一列ずつjoin
        for (int i = 0; i <= r; i++)
            ln(join(A[i], " "));
    }

    public static void main(String[] args) {
        new Main().run();
    }

    public static void ln(Object o) {
        System.out.println(o);
    }

    //StringBuilderで出力する文字列を作成
    public static String join(int[] array, String separator) {
        //1行1列目から最初の一文字(array[0])取得 
        StringBuilder str = new StringBuilder(array[0] + ""); 

        //2文字目から回すことで最後の空白を出力しないようにする
        for (int i = 1; i < array.length; i++) {
            str.append(separator).append(array[i] + "");
        }
        return str.toString();

        //toStringでStringに変換しないとコンパイルエラー
        //return str; 
        //incompatible types: StringBuilder cannot be converted to String
    }
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Java】多次元配列を出力・表計算(AOJ⑤表計算)

StringBuilderで文字列表現を返す

  • StringBuilderで出力する時に気をつけないと以下のエラーに。。
    cannot convert from StringBuilder to String
  • StringBuilderで連結結果をコンソール出力のみなら、printlnメソッドが引数に指定された任意のオブジェクトに対してString.valueOfからのsb.toStringを呼び出す
    • println は引数が文字列でなかったときに toString を呼び出してくれてた
StringBuilder sb = new StringBuilder();
System.out.println(sb);
  • Stringとして結果を得る必要があるならtoStringを明示的に呼び出す
  • StringBuilderのtoStringメソッド
    • 新しいStringオブジェクトを割り当て、初期化し、このオブジェクトの現在の文字列を返す
StringBuilder sb = new StringBuilder();
String result = sb.toString();//OK
String result = sb;  //コンパイルエラー(型が違う)
参考

多次元配列を出力

  • 1次元の配列ではお馴染みArrays.toString
  • 多次元の配列ではArrays.deepToString
import java.util.*;
import java.util.Arrays;
public class Main {
    public static void main(String[] args) throws Exception {
        // 1次元配列
        int[] nums = new int[] { 1, 2, 3 };
        System.out.println(nums);//[I@36baf30c
        System.out.println(Arrays.toString(nums));// [1, 2, 3]
        // 多次元配列
        int[][] nums2 = new int[][] { { 1, 2, 3 }, { 11, 12, 13 } };
        System.out.println(nums2);// [[I@7a81197d
        System.out.println(Arrays.toString(nums2));// [[I@5ca881b5, [I@24d46ca6]

        System.out.println(Arrays.deepToString(nums2));// [[1, 2, 3], [11, 12, 13]]
    }
}

表計算(ITP1-7)

表計算を行う簡単なプログラムを作成します。
表の行数rと列数c、r × c の要素を持つ表を読み込んで、各行と列の合計を挿入した新しい表を出力するプログラムを作成して下さい。
【Input】
最初の行にrとcが空白区切りで与えられます。続くr行にそれぞれc個の整数が空白区切りで与えられます。
【Output】
(r+1) × (c+1) の新しい表を出力して下さい。各行の隣り合う整数は1つの空白で区切って下さい。各行の最後の列としてその行の合計値を、各列の最後の行としてその列の合計値を、最後の行・列に表全体の合計値を挿入して下さい。
【Constraints】
* 1 ≤ r, c ≤ 100
* 0 ≤ 要素 ≤ 100
【入力例】
4 5
1 1 3 4 5
2 2 2 4 5
3 3 0 1 1
2 3 4 4 6
【出力例】
1 1 3 4 5 14
2 2 2 4 5 15
3 3 0 1 1 8
2 3 4 4 6 19
8 9 9 13 17 56

import java.util.Scanner;
import java.util.Arrays;
class Main {
    Scanner sc = new Scanner(System.in);

    public void run() {
        int r = sc.nextInt(), c = sc.nextInt();

        int[][] A = new int[r + 1][c + 1];

        //r × c の要素を持つ表をスキャン
        for (int i = 0; i < r; i++)
            for (int j = 0; j < c; j++) {
                A[i][j] = sc.nextInt();
            }
        //列ごとの合計を計算しc列目に代入
        for (int i = 0; i < r; i++) {
            int sum = 0;
            for (int j = 0; j < c; j++) {
                sum += A[i][j];
            }
            A[i][c] = sum;
        }
        //行ごとの合計を計算しc列目に代入
        for (int j = 0; j <= c; j++) {
            int sum = 0;
            for (int i = 0; i < r; i++) {
                sum += A[i][j];
            }
            A[r][j] = sum;
        }
        //中身確認
        //System.out.println(Arrays.deepToString(A));

        //一列ずつjoin
        for (int i = 0; i <= r; i++)
            ln(join(A[i], " "));
    }

    public static void main(String[] args) {
        new Main().run();
    }

    public static void ln(Object o) {
        System.out.println(o);
    }

    //StringBuilderで出力する文字列を作成
    public static String join(int[] array, String separator) {
        //1行1列目から最初の一文字(array[0])取得 
        StringBuilder str = new StringBuilder(array[0] + ""); 

        //2文字目から回すことで最後の空白を出力しないようにする
        for (int i = 1; i < array.length; i++) {
            str.append(separator).append(array[i] + "");
        }
        return str.toString();

        //toStringでStringに変換しないとコンパイルエラー
        //return str; 
        //incompatible types: StringBuilder cannot be converted to String
    }
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Java】文字取得・boolean型用途(AOJ⑤不足しているカードの発見)

文字列から指定位置の1文字を取得

  • charAtメソッド
  • 文字列.charAt(指定位置);
public class Main {
    public static void main(String[] args){

    String str = "もふもふねこ";
    System.out.println(str.charAt(0)); //も
    System.out.println(str.charAt(3)); //ふ
    System.out.println(str.charAt(4)); //ね
    System.out.println(str.charAt(5)); //こ
  }
}

boolean型の用途

  • boolean型は、true(はい)またはfalse(いいえ)の判定結果を入れるために利用できる
  • 数値や文字列の比較結果を表す
  • if文で分岐の方向を表す
  • for文やwhile文でループを続行するか決定する
//数値比較
public class Main {
    public static void main(String[] args){
    System.out.println("1 = 1 ? : " + (1 == 1)); //1 = 1 ? : true 
    System.out.println("1 = 2 ? : " + (1 == 2)); //1 = 2 ? : false
    }
}

if文の条件分岐で使う方法

//if文で分岐の方向を表す
int a = 0;
int b = 1;
if(a == b) {
  System.out.println("trueの場合に実行");
}
else {
  System.out.println("falseの場合に実行");
}
public class Main {
    public static void main(String[] args){
        // boolean型変数を宣言
        boolean isEighteen = false; 
        int Age = 18; 
        isEighteen = (Age >= 18); 
        System.out.println(isEighteen); //true
        if (isEighteen) { // true 
            System.out.println("18歳以上"); //18歳以上
        } else {
            System.out.println("18歳未満");
        }
    }
}

Whileで使う方法

//while文でループを続行するか決定
import java.util.Scanner;
public class Main {
    public static void main(String[] args){
    int i = 0;
    while(i < 10) {
        System.out.print(i + " ");
        i += 1;
    }
  }
}

Boolean

  • Booleanとは、boolean型ラッパークラスのことで、boolean型を便利に使うためのメソッドを持ちます。
  • Booleanクラス 参照型 クラスまたはインスタンスを参照する
  • Booleanはクラスなのでnull(何も定義されていない参照)
  • toStringメソッド
    • boolean型の値を文字列で返し、trueが入っている時は“true”、falseは“false”が返る
public class Main {
    public static void main(String[] args){
        Boolean bool = Boolean.valueOf(true);
        System.out.println(bool); //true
        bool = null;
        System.out.println(bool); //null
  }
}
public class Main {
    public static void main(String[] args){
        Boolean bool = Boolean.valueOf(true);
        System.out.println(bool.toString()); //true
    }
}

不足しているカードの発見

太郎が花子と一緒にトランプ遊びをしようとしたところ、52枚あるはずのカードが n 枚のカードしか手元にありません。これらの n 枚のカードを入力として、足りないカードを出力するプログラムを作成して下さい。
太郎が最初に持っていたトランプはジョーカーを除く52枚のカードです。
52枚のカードは、スペード、ハート、クラブ、ダイヤの4つの絵柄に分かれており、各絵柄には13のランクがあります。
* Input
最初の行に太郎が持っているカードの枚数 n (n ≤ 52)が与えられます。
続いて n 組のカードがそれぞれ1行に与えられます。各組は1つの空白で区切られた文字と整数です。文字はカードの絵柄を表し、スペードが'S'、ハートが'H'、クラブが'C'、ダイヤが'D'で表されています。整数はそのカードのランク(1 〜 13)を表しています。
* Output
足りないカードをそれぞれ1行に出力して下さい。各カードは入力と同様に1つの空白で区切られた文字と整数です。出力するカードの順番は以下のとおりとします:
* 絵柄がスペード、ハート、クラブ、ダイヤの順番で優先的に出力する。
* 絵柄が同じ場合は、ランクが小さい順に出力する。

import java.util.*;
class Main {

    static char[] symbol = new char[] {'S','H','C','D'};
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        boolean[][] cards = new boolean[4][13];
        for(int i = 0; i < n; i++) {
            char k = sc.next().charAt(0);
            int r = sc.nextInt();
                         //配列は0始まりであることに注意!
            if(k == 'S') {
                cards[0][r-1] = true;
            }
            if(k == 'H') {
                cards[1][r-1] = true;
            }
            if(k == 'C') {
                cards[2][r-1] = true;
            }
            if(k == 'D') {
                cards[3][r-1] = true;
            }
        }
        for(int i = 0 ; i< 4; i++) {
            for(int j = 0; j < 13; j++) {
                if(!cards[i][j]) {
                    System.out.println( symbol[i] + " " + (j+1));
                }
            }
        }
    }
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Java】ArrayListクラスのオブジェクト操作 (AOJ④数列の反転)

ArrayListクラス(可変長配列)のオブジェクト操作

  • リストは配下の要素が順序づけられたコレクション
  • ArrayListは内部的に配列を利用したデータ構造になっていて後からでも要素追加削除可能
    • cf: 配列は不可
  • インデックス値による値の読み書き(ランダムアクセス)は、位置によらず一定時間でアクセス可能
  • 値の頻繁な挿入削除は低速
    • 挿入時に確保していたメモリの領域を超えると自動でメモリ再割り当てが発生する(→あらかじめ要素数が想定される場合サイズ宣言しよう)

定義

  • ArrayList<型> リスト名 = new ArrayList<型>();
    • <型> にクラス名を指定
    • 指定したクラスのオブジェクトを要素として格納できるようになる
    • 基本型を扱うリストを作成したい場合は、ラッパークラスで定義(ex: int型のラッパークラスはIntegerクラス)

要素の並べ替え

  • Collectionsクラスのsortメソッド
  • リストの要素を自然昇順でソート
    • Collections.sort(ArrayListオブジェクト);
  • 要素を降順にソート
    • Collections.sort(ArrayListオブジェクト, Collections.reverseOrder());

要素を逆順に

  • Collectionsクラスのreverseメソッド
  • Collections.reverse(リスト);
import java.util.ArrayList;
import java.util.List;
import java.util.Collections;
import java.util.Arrays;

public class Main {
    public static void main(String[] args) {

    ArrayList<Integer> nums = new ArrayList<Integer>(Arrays.asList(50,80,46));
    nums.add(1);
    System.out.println(nums); //[50, 80, 46, 1]

    //sort関数で昇順に並び替え 
    Collections.sort(nums); 
    //表示して確認 
    System.out.println(nums);  //[1, 46, 50, 80]
    //sort関数で降順に並び替え 
    Collections.sort(nums, Collections.reverseOrder());
    //表示して確認 
    System.out.println(nums);  //[80, 50, 46, 1]

    //リストから2番目の値を取得して表示 
    System.out.println(nums.get(2)); //46

    System.out.println("データ数:" + nums.size()); //データ数:4

    for (int i = 0 ; i < nums.size() ; i++){
      int num = nums.get(i);
      System.out.print(num+" "); //80 50 46 1 
    }
  }
}   

数列の反転

与えられた数列を逆順に出力するプログラムを作成して下さい。
*Input
入力は以下の形式で与えられます:
n
a1 a2 . . . an
nは数列の長さを示し、ai は i 番目の数を表します。
*Output
逆順の数列を1行に出力して下さい。数列の要素の間に1つの空白を入れて下さい(最後の数の後に空白は入らないことに注意して下さい)。
*Constraints
- n ≤ 100
- 0 ≤ ai < 1000

import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n =scanner.nextInt();

        ArrayList<Integer> nums = new ArrayList<Integer>();

        for(int i=1;i<=n;i++){
            int num = scanner.nextInt();
            nums.add(num);
        }

       /*
       昇順に並び替え 
         Collections.sort(nums)
       降順に並び替え 
         Collections.sort(nums, Collections.reverseOrder());
       サイズ確認 
         System.out.println(nums.size()); 
       */
       Collections.reverse(nums);

        for (int i = 0 ; i < n ; i++){

            if (i==n-1){
                System.out.print(nums.get(i));
            }
            else{
            System.out.print(nums.get(i)+" ");
            }
        }
        System.out.println();
    }
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

超初心者が覚えたてのJavaでLoto6の購入案を自動生成する

導入

友人(プログラミング経験者)「お前プログラミング始めたんだって?」

私「うんそだよー」

友人「じゃあLoto6の数字を決めてくれるプログラミング作ってみてよ」

私「余裕でしょ:wink:

始めに

ロト6は、1~43の数字の中から異なる6個の数字を選ぶ数字選択式宝くじです。

タイトルにもあるように私はプログラミング初心者なので、超簡単にJavaでロト6の数字を選んでくれるコードを書こう!の記事です。
当然ながら過去当選番号等をスクレイピングして~なんてことはしません。というかスクレイピングってなに?

奮闘記のような形になってますので、初心者の頃を思い出して生暖かい目で見て頂ければと思います。

案1(ゴリ押し)

早速だけどコードを書いていく。

私「えーと、まずは6個の数字を格納する配列を作って・・・・・・」
私「当然、1~43の数字をランダムで選ぶんだからRandomクラスは必須だよね~」

int[] numbers = new int[6];
for (int i = 0; i < numbers.length; i++) {
    Random random = new Random();
    numbers[i] = random.nextInt(43)+1;
}

私「あれ、これで完成したんじゃ? プログラミングって簡単だな:sunglasses:

私「実行、っと」

result
39
18
7
18
34
11

私「あ・・・そっかあ・・・・・・:sob:

当たり前だが、これでは数字が被ってしまう。上記にもあるが、ロト6は異なる6つ数字が選ばれるので、さすがにこれで完成とは言えない。

私「じゃあ被った場合はもう一度選びなおしてもらうようにしないといけないな~どうしよう」

私「ゴリ押すか:muscle:

do {
    for (int i = 0; i < numbers.length; i++) {
        Random random = new Random();
        numbers[i] = random.nextInt(43)+1;
    }
} while (numbers[0] == numbers[1] || numbers[0] == numbers[2] || numbers[0] == numbers[3] ||
         numbers[0] == numbers[4] || numbers[0] == numbers[5] || numbers[1] == numbers[2] ||
         numbers[1] == numbers[3] || numbers[1] == numbers[4] || numbers[1] == numbers[5] ||
         numbers[2] == numbers[3] || numbers[2] == numbers[4] || numbers[2] == numbers[5] ||
         numbers[3] == numbers[4] || numbers[3] == numbers[5] || numbers[4] == numbers[5]);

完成。
求めていたものはできた。数字は絶対に被らない。

私「見て見て~できたよ~:relaxed:

友人「お、割かし早かったな。どれどれ・・・・・・?」

友人「・・・・・・」

友人「お前・・・・・・」

私「え、俺また何かやっちゃいました?:triumph:

友人「ば! か! や! ろ! う!」

友人「プログラミングってのはなぁ!動けばいいってもんじゃないんだよ!~~(説教)~~」

私「:dizzy_face::dizzy_face::dizzy_face:

案2(メソッド・汎用化)

案1はボツになってしまった。

私「なんかよく分からないけど怒られちゃったなあ」

私「でも確かに書くとき面倒くさかったし、私が思い描くプログラミングって感じじゃないな~」

私「まずは流れを整理しよう。やりたいことはさっき書いたように配列の中の数字が被っているかどうかのチェック。被っていた場合は片方の数字をチェンジ。そしてまた最初からチェックのし直しをする」

私「そうか。配列の0番目~4番目の数字を他の数字と被ってないかチェックするメソッドを作ればいいのか!?」

私「とりあえず乱数を取得するメソッドを作成して、配列に入れる・・・っと」

int[] numbers = new int[6];
    for (int i = 0; i < numbers.length; i++) {
        numbers[i] = getNumbers();
        }

private static int getNumber() {
    Random random = new Random();
    return random.nextInt(43)+1;
}

私「そんでもってcheckメソッドを作ろう」


private static void checkNumber0(int numbers[]) {
    for(int i = 1;i < numbers.length;i++) {
        if(numbers[0] == numbers[i]) {
            numbers[i] = getNumber();
            checkNumber0(numbers);
        }
    }
    checkNumber1(numbers);
}

private static void checkNumber1(int numbers[]) {
    for(int i = 2;i < numbers.length;i++) {
        if(numbers[1] == numbers[i]) {
            numbers[i] = getNumber();
            checkNumber0(numbers);
        }
    }
    checkNumber2(numbers);
}

private static void checkNumber2(int numbers[]) {
    for(int i = 3;i < numbers.length;i++) {
        if(numbers[2] == numbers[i]) {
            numbers[i] = getNumber();
            checkNumber0(numbers);
        }
    }
    checkNumber3(numbers);
}

private static void checkNumber3(int numbers[]) {
    for(int i = 4;i < numbers.length;i++) {
        if(numbers[3] == numbers[i]) {
            numbers[i] = getNumber();
            checkNumber0(numbers);
        }
    }
    checkNumber4(numbers);
}

private static void checkNumber4(int numbers[]) {
    for(int i = 5;i < numbers.length;i++) {
        if(numbers[4] == numbers[i]) {
            numbers[i] = getNumber();
            checkNumber0(numbers);
        }
    }
}

私「できた!」

私「けどこれ、さっきより長くなってない・・・? これ見せたらまた怒られそう・・・」

私「checkNumber〇()の中身って似たようなプログラミングだし、一つに纏められないかな」

ここで冷静に考える。別々のメソッドの中には共通点が多い。数字が違うところも共通項が抜き出せそうだ。

  • 共通項
    • for文の中の変数iはチェックしたい配列[index]の一つ上の数字で初期化されている。
    • [index]番目の中身をチェックしたら一つ上の[index]番目をチェックしに行く。

私「これをプログラミングすればいけそう!」


private static void checkNumbers(int index, int[] numbers) {
    for (int i = index + 1; i < numbers.length; i++) {
        if (numbers[index] == numbers[i]) {
            numbers[i] = getNumbers();
            checkNumbers(0, numbers);
        }
    }
    index++;
    if (index < numbers.length - 1) {
        checkNumbers(index, numbers);
    }
}

完成。さっきよりも断然すっきりした。ドラクエのレベルアップの音が脳内で再生される。

私「渾身の出来だし、さっそく友人に見せに行こう~:smirk:



友人「ふむ。さっきとコード量自体はあまり変わっていないかもしれないが、これでかなり汎用的になったな。これで仕様変更があっても楽になるぞ」

私「ということはこれで合格!?:laughing:

友人「まあ初心者にしては、という枕詞が付くがな。それに合格は合格でも【及第点】というところだ」

私「え~~これでも結構頑張ったのに。それとももっと簡単に書けるの?」

友人「ああ、これよりもっと簡潔にかける。それも頑張って考えてみてくれ」

私「:dizzy_face::dizzy_face::dizzy_face:

案3(完成版)

案2はボツにはならなかったが、友人は及第点しかくれなかった。
ここまできたら友人もアッと驚くようなプログラムを作りたい。

私「とは言ってもどうすればいいんだろう」

ここで流れを整理すると

  1. 配列を宣言する
  2. 配列の中身に乱数を代入する
  3. 配列の中身が他の中身と被ってないかチェックする
  4. 被っていた場合、片方の配列の中身を書き換える
  5. 【3,4】を繰り返す

私「うーん。確かに少し無駄があるかも」

私「【2】で配列の中に変数を代入するときにそれまで入れていた数字と被っていないかチェックすればもっと簡潔にできるかな??」


for(int i = 0;i < numbers.length;i++) {
    numbers[i] = getNumber();
    for(int j = 0 ; j < i ;j++) {
        if(numbers[j] == numbers[i]) {
            numbers[i] = getNumber();
        }
    }
}

完成、、、ではない。当然ながら2回目の

numbers[i]=getNumber();

で、また数字が被ってしまう可能性があるからだ。

私「うーん。案2みたいにこれをメソッド化してif(true)なら一からやり直すようにすればいけそうだけど・・・」

私「一から・・・・・・? :flushed:! いや違う、一減らせばいいだけだ!!

for(int i = 0;i < numbers.length;i++) {
    numbers[i] = getNumber();
    for(int j = 0 ; j < i ;j++) {
        if(numbers[j] == numbers[i]) {
            i--;
            break;
        }
    }
}

私「デクリメント・・・! そういえばこういうのもあったなあ」

私「とにかく、これで最終完成といっていいかな。我ながら無駄なく綺麗なコードが書けたぞ!:blush:

Loto6
public class Loto6{
    public static void main(String[] args) {
        int[] numbers = new int[6];
        for(int i = 0;i < numbers.length;i++) {
            numbers[i] = getNumber();
            for(int j = 0 ; j < i ;j++) {
                if(numbers[j] == numbers[i]) {
                    i--;
                    break;
                }
            }
        }
        for (int i : numbers) {
            System.out.println(i);
        }
    }

    private static int getNumber() {
        Random random = new Random();
        return random.nextInt(43)+1;
    }
}

友人「お!かなりいいコードが書けたな」

私「えへへ:kissing_closed_eyes:

友人「どうだ? こういった考えるプロセスだったり、自分で考えたコードがきちんと動いたときの喜びはでかいだろう」

私「うん! プログラミングって楽しいって思いながらできたよ」

友人「それはよかった。これからも頑張ってくれよ」

私「もちろん。ところで友人だったらどういうプログラムを書くの?」

友人「俺か? 俺ならそうだな・・・」

Loto6
public class Loto {
    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<Integer>();
        for(int i = 1;i <= 43;i++) {
            numbers.add(i);
        }

        Collections.shuffle(numbers);

        for(int i = 0;i < 6;i++) {
            System.out.println(numbers.get(i));
        }
    }
}

友人「ま、ListクラスとCollectionsクラスを使ってパパっと出すかな~」

私「あ ほ く さ」

結論

プログラミング楽しい!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Java】ConcurrentModificationExceptionとは何か

プログラミング勉強日記

2020年11月15日
Javaでコードを書きテストを使用してあっているか確かめていたところ、java.util.ConcurrentModificationExceptionという例外が発生したのでConcurrentModificationExceptionとは何なのか、どうすればいいのかまとめる。

ConcurrentModificationExceptionとは

  ConcurrentModificationExceptionのJavadocには以下のように書いてある。

この例外は、オブジェクトの並行変更を検出したメソッドによって、そのような変更が許可されていない場合にスローされます。

 基本的には、繰り返しているものが変更されたときに早めに失敗して例外を投げるフェイルファーストするために使用される。つまり、繰り返し処理を終了する前に例外が発生している。

 for-each文はIteratorを使用しているが、あまり冗長ではないが、テストでIteratorを使用するようにいリファクタリングした場合はremove()などの追加のメソッドにアクセスできる。removeメソッドがConcurrentModificationExceptionを引き起こさないため、繰り返しの処理中に呼び出しても大丈夫である。

 自分のコードの場合はArrayListの扱い方に問題があった。ArrayListとIteratorは内部で「変更された回数」を保持している。ArrayListのiterator()メソッドで生成されるIteratorはforで回す際に使うnext()メソッドなどを起動した際に,変更された回数にずれがないかチェックしていて、ずれがあったためConcurrentModificationExceptionの例外が発生していた。
 JavadocのArrayListに以下の記述があった。

このクラスの iterator および listIterator メソッドによって返されるイテレータは、フェイルファストです。イテレータの作成後に、イテレータ自体の remove または add メソッド以外の方法でリストが構造的に変更されると、イテレータは ConcurrentModificationException をスローします。このように、並行して変更が行われると、イテレータは、将来の予測できない時点において予測できない動作が発生する危険を回避するために、ただちにかつ手際よく例外をスローします。
通常、非同期の並行変更がある場合、確かな保証を行うことは不可能なので、イテレータのフェイルファストの動作を保証することはできません。フェイルファストイテレータは最善努力原則に基づき、ConcurrentModificationException をスローします。したがって、正確を期すためにこの例外に依存するプログラムを書くことは誤りです。「イテレータのフェイルファストの動作はバグを検出するためにのみ使用すべきです」。

参考文献

クラス ConcurrentModificationException
JavaでConcurrentModificationExceptionを回避

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む