JDBCいろいろ

接続

//接続先URL
String url = "jdbc:mysql://localhost:3306/study?autoReconnect=true&useSSL=false&serverTimezone=UTC";
//ユーザ名
String user = "root";
//パスワード
String pass = "root";
//接続する
//JavaSE7よりtry-with-resourcesが使えるようになっているので、
//クローズし忘れや簡潔なコード記述のためにこう書くのがベター
try (Connection con  = DriverManager.getConnection(url, user, pass)) {
    //SQLの実行はここに書く
} catch (SQLException e) {
    e.printStackTrace();
}

ちなみにURLの個所についていろいろ
例外が出る場合がある。
①The server time zone value ' (W)' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver
②Establishing SSL connection without server's identity verification
URLの部分の、
①autoReconnect=true&useSSL=false
②&serverTimezone=UTC
で、それぞれ対処。 SSL接続をしないこと、サーバのタイムゾーン指定をすることで例外抑止する。

SQLの実行

try (Connection con  = DriverManager.getConnection(url, user, pass)) {
    //Statementオブジェクトの生成
    Statement st = con.createStatement();
    String selectSql = "select * from user";
    String update = "update user set id = 3";
    //select分の発行は#executeQueryを使用する
    st.executeQuery(selectSql);
    //更新SQLの場合は#executeUpdateを使用する
    st.executeUpdate(update);
    //なお、#executeメソッドも存在する
    //executeは結果が存在する場合にtrueを返す
    boolean result = st.execute(selectSql);
    
} catch (SQLException e) {
    e.printStackTrace();
}

SQLの実行②結果の取得・操作

//クエリの結果はResultSetオブジェクトが保持している
ResultSet resultset = st.executeQuery(selectSql);
//更新系は更新件数が戻り値となる
int updateCnt = st.executeUpdate(update);

//ResultSetからのデータ取得
resultset.next();
//このように書くことで結果セットの全レコードに対する処理ができる
while (resultSet.next()) {
    System.out.println(rs.getInt("id"));
}
//

並行処理いろいろ

Runnableを使用した場合

//Runnableオブジェクトを生成する
Runnable r = () -> {
    System.out.println("Task is executed.");
    System.out.println("end");
};

//Executorを使用して実行
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.execute(r);

//Executorは通常ファクトリメソッドを使用して生成する
Executors.newSingleThreadExecutor();
Executors.newCachedThreadPool();
Executors.newFixedThreadPool(3);
Executors.newScheduledThreadPool(2);
//違いはよくわからない(勉強中)

Callableを使用する場合

//Runnableでは戻り値や例外処理ができないため、
//そのような場合はCallbele<T>を使用する
Callable<String> call = () -> {
    return "called!";
};
//Callableを使用する場合はExecutorのsubmitメソッドを使用する
//futureオブジェクトが返却される
Future<String> future = executor.submit(call);
//Callableの実装の戻り値を取得する場合は#get()を使用する
System.out.println(future.get());

なお、タスクの実行が終了しても、Executorそのものは自動的に終了しない。
そのため、#shutdown()を明示的に呼び出す必要がある。

//Executorの終了
executor.shutdown();

ちなみに、Executorの終了後にタスクを実行すると例外が発生する

executor.shutdown();
//Executorの終了後にタスクを実行すると、
//java.util.concurrent.RejectedExecutionExceptionが発生
executor.submit(call);

Fork/Join フレームワーク

//RecursiveActionを継承したクラスを作る
public class MyAction extends RecursiveAction {

    @Override
    protected void compute() {
        
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("MyAction!");
    }

}

//実行側
    public static void main(String[] args) throws Exception {
        ForkJoinPool executor = new ForkJoinPool();
        executor.execute(new MyAction());
        System.out.println("main:ok");
        Thread.sleep(3000);
        System.out.println("done!");
    }

Streamを使った並列処理

List<Integer> list = new ArrayList<>(Arrays.asList(1,2,3,4,5));
//parallelStreamを使用してStream化した場合、並列ストリームになる
//以下のコードは2乗した数字が出る順序は不定
list.parallelStream().map(i -> i * i).forEach(System.out::println);

//順次ストリームへの変換
list.parallelStream()
.map(i -> i * i)
.sequential() //このsequential()を呼び出すことで順次制御になる
.forEach(System.out::println);
//値は一定になる

Java Date and Time API

Java Date and Time APIについていろいろ

//年月日日時
System.out.println(LocalDateTime.now());
//年月日
System.out.println(LocalDate.now());
//時間のみ
System.out.println(LocalTime.now());

結果

2018-05-04T11:36:00.778
2018-05-04
11:36:00.779

LocalDateオブジェクトの生成

//指定した日付のLocalDateを生成
LocalDate day = LocalDate.of(2018, 5, 1);

//月を表すenumがあるので、そちらを使用したほうがよい
LocalDate day2 = LocalDate.of(2018, Month.MAY, 1);

//LocalDateはコンストラクタではなくファクトリメソッドでオブジェクトを生成する

日付の加減算

//基準日の生成(2018/1/1)
LocalDate day = LocalDate.of(2018, Month.JANUARY, 1);
//1年後
LocalDate after1Years = day.plus(1, ChronoUnit.YEARS);
//10日前
LocalDate before10Days = day.minus(10, ChronoUnit.DAYS);

//第1引数に値、第2引数にどの日時単位の加減算をするかを表すchronoUnitを指定する

日付の間の時間量

//月数の時間量
long until = day.until(day2, ChronoUnit.MONTHS);
//日数の時間量
long untilDate = day.until(day2, ChronoUnit.DAYS);

Periodクラスを使用した時間量の計算

//基準日の生成(2018/1/1)
LocalDate day = LocalDate.of(2018, Month.JANUARY, 1);
//基準日の生成(2020/5/25)
LocalDate day2 = LocalDate.of(2020, Month.MAY, 25);

Period period = Period.between(day, day2);
//日付間隔 → 24
int days = period.getDays();
//月間隔 → 4
int months = period.getMonths();
//年間隔 → 2
int years = period.getYears();

日付フォーマッタを使用したフォーマット

LocalDate date = LocalDate.of(2018, Month.MAY, 1);
//BASIC_ISO_DATEでフォーマットする
//これ以外にも基本的なフォーマットはDateTimeFormatterクラスに用意されている
DateTimeFormatter formatter = DateTimeFormatter.BASIC_ISO_DATE;
//2018-05-01
System.out.println(date);
//20180501
System.out.println(formatter.format(date));

//ofPatternを使用すると独自フォーマッタが作成できる
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyねんMMがつddにち");
//2018ねん05がつ01にち
System.out.println(formatter.format(date));

標準入力からの値の読み込み

コーディング問題であるような、最初の1行に規定数、次の行にその数分の入力がスペース区切りであるようなやつ。

       Scanner sc = new Scanner(System.in);
        //最初の1行(e.g. 4)
        int num = Integer.parseInt(sc.nextLine());
        int[] numbers = new int[num];
        //次の入力(e.g. 2 4 6 8)
        for (int i = 0; i < numbers.length; i++) {
            numbers[i] = Integer.parseInt(sc.next());
        }

新しいシェルプログラミングの教科書

これ読み始めた

新しいシェルプログラミングの教科書

新しいシェルプログラミングの教科書

String#join

前回に引き続き、文字列の連結。

//String#joinメソッド。第一引数に区切り文字
//文字列連結
String joined = String.join(",", "a", "b", "c");
System.out.println(joined);
        
//String配列の要素の連結
String[] arr = {"aa", "bb", "cc"};
String arrJoined = String.join(":", arr);
System.out.println(arrJoined);
        
//List<String> の要素の連結
List<String> list = Arrays.asList("aaa", "bbb", "ccc");
String listJoined = String.join("*", list);
System.out.println(listJoined);

//Streamを使用した場合
List<String> list2 = Arrays.asList("XX", "YY", "ZZ");
String listJoined2 = list2.stream().collect(Collectors.joining("|"));
System.out.println(listJoined2);

結果

a,b,c
aa:bb:cc
aaa*bbb*ccc
XX|YY|ZZ

StringJoinerによる文字列連結

       //StringJoinerのコンストラクタに区切り文字を渡す
        StringJoiner joiner = new StringJoiner(",");
        //StringJoinerに連結する文字列を追加していく
        joiner.add("one");
        joiner.add("two");
        joiner.add("three");
        joiner.add("four");
        //toStringを呼び出す
        System.out.println(joiner.toString());

結果

one,two,three,four

メソッドチェーンでも

//上と同じ結果
joiner.add("one").add("two").add("three").add("four");

プレフィックスとサフィックスも付けられる

       StringJoiner joiner = new StringJoiner(",","(",")");
        joiner.add("one").add("two").add("three").add("four");
        System.out.println(joiner.toString());

結果

(one,two,three,four)