エンターテイメント!!

遊戯王好きのJavaエンジニアのブログ。バーニングソウルを会得する特訓中。

Java13リリース前の予習

書こうと思ったきっかけ

そろそろリリースが近づいて来たので、まとめようと思い一念発起した。
サイト見る限り、最終リリース候補が出てるようなので、もう、大きな変更はないだろうから、キャッチアップしても大丈夫だろうという考えもある。

各種サイトへのリンク

https://openjdk.java.net/projects/jdk/13/

JDK 13 Early-Access Builds

JEP

  • 350: Dynamic CDS Archives
  • 351: ZGC: Uncommit Unused Memory
  • 353: Reimplement the Legacy Socket API
  • 354: Switch Expressions (Preview)
  • 355: Text Blocks (Preview)

ざっくり読んだ感じ、開発者に影響がありそうなのは、JEP 354/JEP 355

JEP 353も影響ありそうかと思ったけど、内部の実装の変更のようなので、調査対象から外した。
Google翻訳でやってるから、微妙に違うところがあるかも。。。
あと、見てて思ったが、JavaでSocketAPIを直に見るのは、学生のとき以来だなって思った。

354: Switch Expressions (Preview)

簡単に言うと、switchの結果を変数に入れられるようになった。

テストコード

下記の通り、テストコードを作成
java12のやつを流用して作った。

import java.util.Calendar;
import static java.util.Calendar.*;

public class jep354sample {
  public static void main(String[] args) {
    int day = Calendar.getInstance().get(Calendar.DAY_OF_WEEK);
    int numLetters = switch (day) {
      case MONDAY, FRIDAY, SUNDAY -> 6;
      case TUESDAY                -> 7;
      case THURSDAY, SATURDAY     -> 8;
      case WEDNESDAY              -> 9;
      default -> 0;
    };
    
    System.out.println("numLetters:" + numLetters);
  }
}

実行

最初、defaultがない状態でコンパイルしようとしたら、下記の通り、コンパイルエラーになった。

$ javac --enable-preview --release 13 jep354sample.java 
jep354sample.java:7: エラー: switch式がすべての可能な入力値をカバーしていません
    int numLetters = switch (day) {
                     ^
注意:jep354sample.javaはプレビュー言語機能を使用します。
注意:詳細は、-Xlint:previewオプションを指定して再コンパイルしてください。
エラー1個

網羅されてないとエラーになるようになったんだな。。。
それとも、前から?
Java12のときは、エラーにならなかった気がするが、気のせいかな?

本題とはそれるので、とりあえず、コンパイル&実行

$ javac --enable-preview --release 13 jep354sample.java 
$ java --enable-preview jep354sample
numLetters:8

土曜日なので、SATURDAYだから、8で正解。
どうでもいい話だが、SATURDAYは、一週間が終わったから「去ったデー」って習った。

注目スべきは、switchの戻り値があるところだろう。
これで、ケースに応じて結果を返せるようになった。
個人的には、defualtの挙動の方が驚いた。。。

swiftの画面遷移とかで使うswitchの使い方に近いことができるのではないかと思う。

yield

yieldっていう結果返すワードが追加されたので、試す。

テストコード

public class Jep354YieldSample {
  public static void main(String[] args) {
    String day = "xxx";
    int j = switch (day) {
        case "MONDAY"  -> 0;
        case "TUESDAY" -> 1;
        default      -> {
            int k = day.toString().length();
            System.out.println("default day:" + day);
            int result = f(k);
            yield result;
        }
    };
    
    System.out.println("j:" + j);
  }
  
  private static int f(int k) {
    return k + 10000;
  }
}

実行

実行したら、下記の通り。

$ javac --enable-preview --release 13 Jep354YieldSample.java 
$ java --enable-preview Jep354YieldSample
default day:xxx
j:10003

caseの中で計算が必要なときに使うのだろうけど、必要なのか疑問に感じてしまう。。。
とりあえず、新しい動きなので、覚えておいて損はないだろう。

355: Text Blocks (Preview)

開発者が定義した通りの文字列を定義できる。 エスケープ処理が入るので、開発者は、\nとかを気にしなくていい

テストコード

import javax.script.ScriptEngineManager;
import javax.script.ScriptEngine;

public class Jep355Sample {
  public static void main(String[] args) throws Exception {
    String html = """
              <html>
                  <body>
                      <p>Hello, Saga!!</p>
                  </body>
              </html>
              """;

    System.out.println("== html ==");
    System.out.println(html);
    System.out.println("==========");

    String query = """
               SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`
               WHERE `CITY` = 'INDIANAPOLIS'
               ORDER BY `EMP_ID`, `LAST_NAME`;
               """;

    System.out.println("== sql ==");
    System.out.println(query);
    System.out.println("=========");

    ScriptEngine engine = new ScriptEngineManager().getEngineByName("js");
    Object obj = engine.eval("""
                            function hello() {
                                print('"Hello, Saga!!"');
                            }
                            
                            hello();
                            """);
  }
}

やってるのは、HTMLとSQLの表示、JSの実行。

実行

$ javac --enable-preview --release 13 Jep355Sample.java 
$ java --enable-preview Jep355Sample
== html ==
<html>
    <body>
        <p>Hello, Saga!!</p>
    </body>
</html>

==========
== sql ==
SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`
WHERE `CITY` = 'INDIANAPOLIS'
ORDER BY `EMP_ID`, `LAST_NAME`;

=========
Warning: Nashorn engine is planned to be removed from a future JDK release
"Hello, Saga!!"

エスケープ文字列入れてないのに、ちゃんと改行されて、きれいにHTMLとSQLが出力される。
jsも、エスケープ処理なくても、きちんと実行できて"Hello, Saga!!"が出力される。

簡単なDBアクセスでSQL発行するサンプルを作りたいとか、簡単にできそう。
できれば、文字列の代入もあるといいかなと思う。
いちいちプラスで連結するのは、面倒。
Swiftみたいに、\()で代入できると楽なんだが、対応予定はあるのかな?

感想

355: Text Blocks がとても気になる。
文字列操作がもどかしいことがよくあるので、これからも継続的に改善があると嬉しい。

スケジュール通りに進んでいるようなので、Java13も予定通りリリースされると思う。

luceneで文章の類似性を試す

きっかけ

Javaで文章の類似性を数値化できないか調べたところ、luceneというライブラリで実現可能なようなので、サンプル実装して動かしてみた。

環境

IntelliJ IDEA 2019.2.1 (Community Edition)
Build #IC-192.6262.58, built on August 20, 2019
Runtime version: 11.0.3+12-b304.39 amd64
VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
Windows 10 10.0
GC: ParNew, ConcurrentMarkSweep
Memory: 2002M
Cores: 4
Registry: 
Non-Bundled Plugins: net.seesharpsoft.intellij.plugins.csv

実装

GitHub - suzaku-tec/sample-lucene

githubにコード載せておいたので、適時参照してね。

Gradle dependencies

必要になるのは、下記

    // https://mvnrepository.com/artifact/org.apache.lucene/lucene-core
    compile group: 'org.apache.lucene', name: 'lucene-core', version: '8.2.0'

    // https://mvnrepository.com/artifact/org.apache.lucene/lucene-spellchecker
    compile group: 'org.apache.lucene', name: 'lucene-spellchecker', version: '3.6.2'

今回試す分は、上記だけで大丈夫。

TestBatch.java

import org.apache.lucene.search.spell.JaroWinklerDistance;
import org.apache.lucene.search.spell.LevensteinDistance;

public class TestBatch {

    public static void main(String[] arg) throws Exception {

        String one = "今日の東京は非常に寒いです。でも、天気は快晴ですよ!";
        String two = "今日の京都は非常に暑いです。";

        //1に近いほど似ている
        LevensteinDistance l_algo = new LevensteinDistance();

        JaroWinklerDistance j_algo = new JaroWinklerDistance();

        System.out.println("実行結果(LevensteinDistance):" + l_algo.getDistance(one,two));
        System.out.println("実行結果(JaroWinklerDistance):" + j_algo.getDistance(one,two));

    }

}

やることは、インスタンスを生成して比較するだけ。

実行すると、下記のような表示になるはず。

実行結果(LevensteinDistance):0.42307693
実行結果(JaroWinklerDistance):0.7990983

感想

意外と簡単に試せた。
比較のアルゴリズムが、全然分からないから、調査が必要そう。
たぶんだが、コサイン類似度を使ってるんだろうなって気はする。

タスク

参考サイト

Java で Firebase を使う方法のまとめ。 | ソフトコミュ開発ブログ

2つの文字列がどれだけ類似しているかを判定するレーベンシュタイン距離とジャロ・ウィンクラー距離(Java編) | ぱーくん plus idea

windowsにgiboを導入

きっかけ

windows.gitignore作りたかったから。
作るのが死ぬほどめんどくさい。

環境

OS

当然windowsですよ。
念のため、環境情報載せておく

>ver
Microsoft Windows [Version 10.0.18362.295]

Git

>git --version
git version 2.9.0.windows.1

やりかた

やることリスト

  1. giboのダウンロード
  2. パスを通す
  3. 実行可能か確認

giboのダウンロード

任意のディレクトリにgithubから落としてくる。
後でパスを通すので、tmpとかは辞めたほうがいいと思う。

実行コマンドは、下記の通り

git clone https://github.com/simonwhitaker/gibo.git

パスを通す

落としたら、giboディレクトリにパスを通す。

E:\dev\配下にcloneしたら、gibo ディレクトリができると思うので、E:\dev\gibo環境変数に登録
自分は、システム環境変数に登録しました。

確認

下記コマンドを実行する。

gibo version

下記のような表示が出てくれば、実行環境の構築は成功

>gibo version
gibo 2.2 by Simon Whitaker <sw@netcetera.org>
https://github.com/simonwhitaker/gibo

使い方

macと使い方は変わらないので、まとめた下記の過去記事を参照

suzaku-tec.hatenadiary.jp

感想

もっと面倒くさいと思ったけど、案外楽にやれた。
macだと、homebrewが手軽すぎて、「windowsの敷居が高いのでは?」と勝手に妄想してた。

参考サイト

【入門】Windowsでgiboを用いるための環境構築とgiboの使い方 - Qiita

githubのssh-keyの登録

きっかけ

いつも迷うから。

やることは大筋理解しているのだが、面倒で手軽な方向にばかり逃げてきたので、自戒のためにまとめる。

前提条件

githubに登録するので、前提条件としては、githubのアカウント/リポジトリがあることとする。
また、vi操作は、できるものとして話を進める。

環境

OS

$sw_vers
ProductName:    Mac OS X
ProductVersion: 10.14.6
BuildVersion:   18G87

mac前提です。
windowsだと、sshクライアントがデフォルト付いてないのが嫌なので、やっぱり開発はmacでってなってしまう。
cygwin入れればいいのだろうけど、インストールが面倒なんだよね。
時間もかかるし。

Git

$git --version
git version 2.22.0

毎回、git -v をやって怒られてしまう。
ailiasつければいいのだろうが、あんまりailiasに頼りすぎると、環境を一から作るときに苦労しそうなのでやめてる。
他の人はどうしているのだろう?
「そもそも、gitのバージョンなんて確認しねーよ」って人がほとんどだろうか?

やり方

道筋

大まかなやり方の方針を、まずはざっくり理解する。

  1. ssh-keyの生成
  2. 設定ファイルの作成
  3. githubに公開鍵を登録
  4. ssh接続のテスト

ssh-keyの生成

まずは、公開鍵と秘密鍵を作る。

$ cd ~/.ssh
$ ssh-keygen -t rsa -C <メールアドレス>

ディレクトリは、~/.ssh以外でもいいけど、指定があとあと面倒になるので、なるべくここにした方が無難。

ssh-keygenを実行すると、何回か質問される。
Enter file in which to save the key (/Users/<ユーザ名>/.ssh/id_rsa):は、他の場所に保存するかどうか聞かれる。
あんまり場所を移すと、あとあとどこに何をおいたのか分からなくなるので、デフォルトのまま、何も入力せずにenterする。

Enter passphrase (empty for no passphrase):は、見た通り、パスワード設定。
これを入力すると、確認のために、再度入力を求められるので、もう一回入力してenter。

そうすると、~/.ssh/下に、id_rsa/id_rsa.pubが出来上がる。
ファイルの内容は、下記の通り。
id_rsa : 秘密鍵
id_rsa.pub : 公開鍵

設定ファイルの作成

鍵の管理を容易化するために、設定ファイルを追加する。
なければ、新規作成。

$ vi ~/.ssh/config

下記を追記する。

Host github.com
  HostName github.com
  IdentityFile ~/.ssh/id_rsa
  User git

githubに公開鍵を登録

やっと登録。
まずは、githubにサインインする。
サインインできたら、右上のアカウントアイコンを押下して、Settingsを選択。

f:id:suzaku0914:20190816141755p:plain

そしたら、左のメニューから、SSH and GPG keysを選択。 SSH keysの右側にあるnew ssh keysボタンを押下。

titleは、適当に入力。
keyには、id_rsa.pubの内容をコピペする。
下記のコマンドで、クリップボードにコピーしてペーストすると、楽チン。

$ pbcopy < ~/.ssh/id_rsa.pub

入力が終わったら、Add SSH keyボタンを押下して登録。
そうすると、一覧画面に登録した内容が表示されているはず。

ssh接続のテスト

もろもろの登録が終わったので、ちゃんと動作するのかテストする。
失敗したまま進むと、何が問題か分からなくなるので、何事も一個一個、こまめに確認しながら進むことが大事。

下記のコマンドで、ssh接続してみる。

$ ssh -T git@github.com

Are you sure you want to continue connecting (yes/no)?って聞かれたら、とりあえずyes
Enter passphrase for key '/Users/<ユーザ名>/.ssh/id_rsa':って聞かれるので、ssh-keygenで入力したパスワードを入力。
通信が成功すると、Hi <githubアカウント名>! You've successfully authenticated, but GitHub does not provide shell access.って表示されるはず。

感想

やることは簡単なんだけど、やるとなると面倒臭く感じるのは、俺が怠惰だからかも知れない。
githubは、privateリポジトリが誰でも作れたりするようになったので、ssh-keyを作成する需要は上がるかもって思って、まとめ記事を書いてみた。
実際、何も見ないでssh-keyを生成・登録できる人って、少数だと思いたい。少なくとも、俺は無理。何回も調べちゃう。

sshの概念って、わかっちゃいるけど、いざやるとパニクる時代が懐かしいなと感じた。
まだ、IT初心者の頃は、知識としてsshは知っていても、いざ問題に直面すると、フリーズしてしまった頃があった。
今は、簡単に問題解決できるように成長した俺を褒めたい。

参考サイト

GitHubにSSH接続できるようにする方法 - Qiita

GitHubでssh接続する手順~公開鍵・秘密鍵の生成から~ - Qiita

giboの使い方とまとめ

きっかけ

gitの初回登録で、ソース管理の必要がないものを、よく追加してしまうので、何かgitignoreのよい生成方法はないかと探した結果を残す

環境

OS

$sw_vers
ProductName:    Mac OS X
ProductVersion: 10.14.5
BuildVersion:   18F132

Homebrew

$brew -v
Homebrew 2.1.9
Homebrew/homebrew-core (git revision 2548c; last commit 2019-08-11)
Homebrew/homebrew-cask (git revision 64623; last commit 2019-08-11)

git

$git --version
git version 2.22.0

gibo

公式サイト

GitHub - simonwhitaker/gibo: Easy access to gitignore boilerplates

インストール

githubのREADME.mdにある通り、Homebrewでインストールする。
Homebrewのインストールは、ここでは詳しく説明しないので、各自でインストール

brew install gibo

インストール成功確認

インストールがちゃんとできているか、バージョン情報の出力で確認。
こういうのを怠ると、あとあとで手痛い目にあうので、着実にできることは確認した方がよいということを、最近学んだ。

$gibo -v
gibo 2.2.3 by Simon Whitaker <sw@netcetera.org>
https://github.com/simonwhitaker/gibo

Fetches gitignore boilerplates from https://github.com/github/gitignore

Usage:
    gibo [command]

Example:
    gibo dump Swift Xcode >> .gitignore

Commands:
    dump BOILERPLATE...   Write boilerplate(s) to STDOUT
    help                  Display this help text
    list                  List available boilerplates
    root                  Show the directory where gibo stores its boilerplates
    search STR            Search for boilerplates with STR in the name
    update                Update list of available boilerplates
    version               Display current script version

上記のような出力になれば成功しているhazu.

使ってみる

基本的に使うコマンドは、gibo dump <BOILERPLATE>が主になってくると思う。
やっていることは、指定したものの.gitignoreの設定を標準出力に吐き出すというもの。
なので、.gitignoreに出力して作成するのが、主な使い方になっている。

BOILERPLATEには、複数指定が可能なので、使いたい環境に合わせて指定していく。
gibo -hのExampleだと、SwiftとXcodeで必要なgitignoreの設定を出力している。

BOILERPLATEに指定可能な値は、gibo listで確認ができる。

各コマンドの説明

dump

フォーマット

gibo dump [BOILERPLATE]

説明

BOILERPLATEに指定した環境のgitignoreをコンソール上に出力する。

help

フォーマット

gibo help

説明

ヘルプの表示

list

フォーマット

gibo list

説明

BOILERPLATEに指定できる値の一覧を表示する。

root

フォーマット

gibo root

説明

giboのBOILERPLATEを保存しているディレクトリを表示する。 BOILERPLATEを修正したい場合は、ここを修正すれば良さそう。(確認はしてない)

search STR

フォーマット

gibo search <STR>

説明

STRの文字列を含む環境を調べることができる。

$gibo search mac
Emacs
macOS

update

フォーマット

gibo update

説明

BOILERPLATEを更新する。

version

フォーマット

gibo version

説明

giboのバージョンを表示する。

所感

.gitignoreを手作りするのは、やっぱり無理がある。
一度登録してしまった不要なファイルを、消すのが面倒なので、なるべく手軽にgitignoreを作ることは、非常に大事だと思う。

制約が少なそうなツールなので、環境を汚したり、何かと競合するようなことは、少ないさそう。
なので、いまは、giboで落ち着いている。

基本的に使うのは、dumpとlistくらい。
というか、ほぼdump。
覚えるコマンドが少なくて済むのも、良いところだと思いました。

参考サイト

giboで簡単に最適な.gitignoreを作成 - Qiita

.gitignoreはgiboで自動生成しよう - にわとりプログラマーの備忘録

2019/07/29週 気づきと振り返り

業務こなしての問題・気づき

SwiftのレイアウトはLabel優先

入力しない項目は、テキストフィールドじゃなくてラベルで対応する。
複数行に渡るものも、Labelで出す。
テキストフィールドを編集不可とかで表示しようとすると疲れるだけ。

SwiftでLabelのテキストの垂直方向の調整

不可
理由は、分からない。 viewでラップして対応するのが無難そう。

Swiftのコードスタイル

作ってると、なんかネストが深くなりがちなのだが、回避する方法はあるのか?
if let で、ものすごくネストが深くなってしまう。

githubのデフォルトブランチ

githubでは、デフォルトのブランチは、masterになる。

なので、masterを消したりする場合は、defaultを変える必要がある。

Cocoapodsのバージョン固定

cocoapodsのバージョン違いによるエラーが発生する場合がある。
それを回避するためには、gemfileでcocoapodsのバージョンを固定するのがベター

swiftのtableviewでのdetail text label

ストリーボードで設定することができる。
StyleのRight Detailで設定可能。

コード上でも設定できる。
個人的には、動的に変わったりするので、コード上に設定するほうが無難だと思ってる。

2019/07/22週 気づきと振り返り

業務こなしての問題・気づき

macのterminalで、現在ディレクトリをfinderで開く

open .

基本的な使い方は、open <path>
たぶん、使うケースは、open . が多い気がする。
コマンドでやるとタイピングミスしそうって場合は、finderで操作したりしたい性分なので、たまに使う。

gitignoreをかんたんに作成する

giboでやると、ものすごく楽にできる。
どこかのタイミングでまとめるが、深く考えなくても、不要なファイルやパターンを出力できるので、初期開発のスタートダッシュができると思った。
インストールも、Homebrewでかんたんに入れられるのも、良かった。
もう、Homebrewはデファクトスタンダード化している気がする。
デフォルトインストールしないのかな?

TabBarControllerとNavigationController

ラップの順序が大事。 navi → tabだと、画面遷移する際の値渡しが、面倒。
たしか、self.super.~~~とか、書かねければ行けなかった気がする。

シンプルに使いたいのなら、tab → navi の順序でラップする。

雑記

最近、夜が眠れない。
悪方向に考えが言って、なかなか寝れないんだよね。。。。
そのうち、不眠症になったりしないか不満。
調べると、寝る前に悪いことを考えると、自己暗示にかかって悪い方向に行く的な記事を見かけて、かなりガクブル状態なんですけど。。。

寝付けないと、翌日の朝は、寝坊しちゃうんだよね。。。
その時は、急いで会社に行っても居たたまれないので、仮病使って、午前休にする。
そんでもって、余裕をもって出社する。
毎回使うと、流石に怪しまれるので、なるべく使わないようにはしている。