takeda_san’s blog

JavaFXとDeeplearning4jを頑張る方向。

コレクションにファクトリーメソッドが追加されたらしい

まだまだ続くよJava9お試し。
今回はコレクションフレームワークのお話。

List<String> list = new ArrayList<>();
list.add("ひとつめ");
list.add("ふたつめ");

Map<String, String> map = new HashMap<>();
map.put("きー1", "ばりゅー1");
map.put("きー2", "ばりゅー2");

Set<String> set = new HashSet<>();
set.add("いち");
set.add("に");

リスト、マップ、セットの実装数あれど、使うのは大体この3クラス。
右辺の総称型の中身を書かなくてよくなって、少し楽になりましたが、初期化もちょっと簡単に書けるようになりませんかね・・・?
というわけで、Java9からファクトリーメソッドが用意されました。

Javadocのofメソッドが、該当します。

List (Java Platform SE 9 [build 171])

Map (Java Platform SE 9 [build 171])

Set (Java Platform SE 9 [build 171])

まぁ、なんだ…引数多いな。
言いたいことはよくわかるが…引数多いな。特にmap。
コード補完みてると、圧倒的な存在感だぞ。

f:id:takeda_san:20170526233448p:plain

で、書き直したのがこちら。

List<String> list = List.of("ひとつめ", "ふたつめ");
Map<String, String> map = Map.of("きー1", "ばりゅー1", "きー2", "ばりゅー2");
Set<String> set = Set.of("いち", "に");

すっきり。
ちなみに、ofで作成したコレクションは不変になるとのことで変更しようとすると実行時に怒られます。

List<String> list = List.of("ひとつめ", "ふたつめ");
list.add("みっつめ");
Exception in thread "main" java.lang.UnsupportedOperationException
    at java.base/java.util.ImmutableCollections.uoe(Unknown Source)
    at java.base/java.util.ImmutableCollections$AbstractImmutableList.add(Unknown Source)
    at Main.main(Main.java:12)

Java9から匿名クラスの総称型も省略して書けるって本当ですか!?

わかった気になっているうちにやっておこうシリーズ第二弾。
EclipseでJDK9-eaの設定をする記事はこちら。

takeda-san.hatenablog.com

Java9から匿名クラスの総称型もダイヤモンド演算子(って言い方でいいの?)で省略して書けるらしい。
試してみようじゃないの。

というわけで、よくみるJavaFXのカラムクラス内でセルの定義を匿名クラスで作るコードで検証。
(大人気のJavaFXだからね、よくみるよね、ね?)

というわけで、テーブルカラムを継承して自分のテーブルカラムを作る。
そしてその中で、テーブルセルの挙動を変えたい!みたいなコード。

package application;

import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;

public class TestColumn extends TableColumn<Person, String> {

    public TestColumn() {
        // セルをつくるぞ!
        this.setCellFactory(column -> {
            return new TableCell<Person, String>() {
                @Override
                protected void updateItem(String item, boolean empty) {
                    super.updateItem(item, empty);

                    if (!empty) {
                        // なんか処理
                    }
                }
            };
        });
    }
}

で、ここを毎回、えーと型はなんだったかな…?とクラスの先頭までスクロールしてコピペして書くのがめんどくさい。

       this.setCellFactory(column -> {
            return new TableCell<Person, String>() {

でも、書かないと怒られる。
匿名クラスじゃなきゃできるんだからさっ。ねっ?

で、書き換えてみました。

       this.setCellFactory(column -> {
            return new TableCell<>() {

お、エラーが出ない。
素晴らしい。

念のため、コンパイルのレベルを1.8に戻してみる。

f:id:takeda_san:20170525231644p:plain

やっぱり怒られるよね。

今回の内容とは関係ないけど、Eclipseなんだかjavafxパッケージの下にあるクラスがコード保管されない・・・?
久しぶりにimport文を自分で書いたよね。

EclipseでJigsawしてみる その2

というわけで続きです。

takeda-san.hatenablog.com

jar作成死闘編

ようやくjdk9-eaの設定に成功したので、コードを書いていきましょう。

今回は、ライブラリ用のプロジェクトとそれを使うアプリケーションのプロジェクトの二つを準備しました。
まずは、ライブラリ用のプロジェクト。

f:id:takeda_san:20170523225308p:plain

Lib.java … 外部公開API用のクラス

package lib;

import lib.util.LibUtil;

public class Lib {

    public static void outputTextLib() {
        System.out.println("Libですよー。");
        LibUtil.outputTextUtil();
    }
}

LibUtil.java … 外部には公開したくない、Lib.javaが参照するユーティリティクラス(という設定

package lib.util;

public class LibUtil {

    public static void outputTextUtil() {
        System.out.println("LibUtilですよー。");
    }
}

module-info.java … 公開パッケージを記載する
これ、module lib のlibのところはモジュール名なので、適当な名前をつけてよいらしい。
(偶然パッケージ名とおなじになっているだけ)

module lib {
  exports lib;
}

んで、module-info.javaをsrc直下に置くわけだけども、EclipseのNew→New Java Classで作成すると
『Type name is not vaild』って怒られるのね。(クラス名に"-“が入っているから当たり前か)
なので、New→New Fileで作りました。

このページにも、そうせよと書いてある。

Eclipse and Jigsaw modules - Eclipsepedia

で一通り、ファイルはできたのでコンパイルしてjarにまとめたいんだけど jarのExportが、下のエラーでどうあがいてもできないわけですよ。

『JAR creation failed. See details for additional information. Class files on classpath not found or not accessible for: ‘Lib/src/module-info.java'』

クラスファイルがないだと・・・?
と、binフォルダの下を見るとしっかりmodule-info.classがあるわけですよ。
しばらく調べてもよくわからなかったので、悔しいけれど、コマンドでjarを作ります。

いつものjarコマンドとは違うやり方が必要だった気がするので、jar –helpでコマンドを調べてみます。

 # 2つのクラス・ファイルを含むclasses.jarというアーカイブを作成する:
 jar --create --file classes.jar Foo.class Bar.class
 # foo/のすべてのファイルを含む、既存のマニフェストを使用したアーカイブを作成する:
 jar --create --file classes.jar --manifest mymanifest -C foo/ .
 # モジュラjarアーカイブを作成する。モジュール・ディスクリプタはclasses/module-info.classに
 # ある:
 jar --create --file foo.jar --main-class com.foo.Main --module-version 1.0
     -C foo/ classes resources
 # 既存の非モジュラjarをモジュラjarに更新する:
 jar --update --file foo.jar --main-class com.foo.Main --module-version 1.0
     -C foo/ module-info.class
 # 複数リリースjarを作成し、一部のファイルをMETA-INF/versions/9ディレクトリに配置する:
 jar --create --file mr.jar -C foo classes --release 9 -C foo9 classes

うーん、ようわからん。
とりあえず–createを付ければいいんかな。

C:\Users\takeda\eclipse-workspace\Lib\bin>"C:\Program Files\Java\jdk-9\bin\jar.exe" --create --file=lib.jar .

動作確認編

とりあえず、jarはできたので、アプリケーションのプロジェクトにインポートしてみる。

f:id:takeda_san:20170523231602p:plain

App.java … メインクラス

package app;

import lib.Lib;

public class App {

    public static void main(String[] args) {
        Lib.outputTextLib();
    }
}

module-info.java … 依存するモジュール名を記載する (偶然パッケージ名とおなじになっているだけ)

module app {
  requires lib;
}

で、コンパイル後に実行するわけだけれどもlibパッケージが見えなくてエラーが出ている。
そういえば、設定を一つ忘れていたな…

Java 9 Support (BETA) for Oxygen | Eclipse Plugins, Bundles and Products - Eclipse Marketplace

added to the .classpath manually: <classpathentry kind="con" path="org.eclipse.jdt.MODULE_PATH"/>

モジュールの依存関係をクラスパスに追加せよとのこと。
プロジェクトフォルダ直下の.classpathファイルに追記する。

<?xml version="1.0" encoding="UTF-8"?>
<classpath>
    <classpathentry kind="src" path="src"/>
    <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-9"/>
    <classpathentry kind = "con" path = "org.eclipse.jdt.MODULE_PATH" />
    <classpathentry kind="lib" path="C:/Users/takeda/eclipse-workspace/App/lib/lib.jar"/>
    <classpathentry kind="output" path="bin"/>
</classpath>

んで、読み込みなおしのためワークスペース開きなおし。

f:id:takeda_san:20170523233236p:plain

お、若干参照するライブラリの表示が増えている。
もう一度、コンパイル&実行。

Libですよー。
LibUtilですよー。

長い、戦いだった… 肝心のLibUtilのほうが参照できないか確認してみましょう。

f:id:takeda_san:20170523233535p:plain

お、参照できない。
素晴らしい。

まとめ

2017/5/23時点での内容です。
Java 9、Eclipse Oxygen共に正式リリースまでには、もっと使いやすくなると思います。

Eclipseの現行バージョンNEONでは、Jigsawできないので開発中の次バージョンOxygenを使う
・Oxygen単体では、Java9が使用できないので『Java 9 Support (BETA) for Oxygen』プラグインを入れる
・そのうえで、モジュール化するなら、クラスパスに追加設定が必要
Eclipseからは、module-infoを使ってのjar作成は無理(?)なので、コマンドでつくる
・コマンドでjarを作成する場合は、いつものコマンドに『–create』をつける

EclipseでJigsawしてみる その1

Java Day Tokyo 2017に行ってきた。
わかった気になっているうちに、実践。

エディタで書いて、コマンドラインでビルドと実行?
とんでもない、いつものEclipseで書きます。

JDK9-eaダウンロードしてインストールして、Eclipsejreを追加…
あれ、『Target is not a JDK root. System library was not found』。
いやいやいや、あるじゃないですか。

f:id:takeda_san:20170522232309p:plain

と、おもったらNEON.3時点ではJava 9用のモジュールが入ってないんだってさ。
ちぇっ。
念のために、pleiadesも落としてやってみたけど、まぁ同じよね。
『ターゲットは JDK ルートではありません。システム・ライブラリーが見つかりませんでした。』

Bug 494481 – [1.9]Java9 JRE reports "Target is not a JDK root. System library was not found"

このページによるとOxygen落として、プラグイン入れてから出直して来いよ!
とのこと。
Oxygenってなんだろかと、さらに調べると。 Neonの次のバージョン名らしい。(おしゃれな名前じゃないの)
ここから、Eclipse Oxygen M7(6以降ならOKらしい)をもってくる。
しかし、ダウンロード遅い。

https://www.eclipse.org/downloads/packages/release/Oxygen/M7

あら、スプラッシュ画像がスタイリッシュ。

f:id:takeda_san:20170523001218j:plain

解凍後、マーケットプレイスから「Java 9 Support (BETA) for Oxygen」をインストール。

f:id:takeda_san:20170522235327p:plain

んで、下記のページの通りもうちょっと設定が必要。

https://marketplace.eclipse.org/content/java-9-support-beta-oxygen

eclipse.iniに「–add-modules=java.se.ee」を追加。
【5/23追記 5/23のパッチで必要なくなったみたいです】
で、再度jrejdkを検索してみる。

f:id:takeda_san:20170523001824p:plain

とりあえず、認識はしてくれたみたい。
環境設定で2時間。まさかのコードを書くことなく次回へ続く。
(調べてる途中で、IntelliJのcommunity版でjdk9-eaを設定してみたら一瞬で設定完了したのは内緒。Eclipseを信じろ。)

続きの記事はこちら

takeda-san.hatenablog.com

JavaFXのテーブル行の文字色をまとめて設定したい

結論から書くと、次のスタイルを指定すればよい。

-fx-text-background-color

参考にしたのは下記のページ。
やはり、スタイルの設定をしたければ、まずmodenaの定義を見よ。ということに尽きる。
(以前にもtreetableの偶数行の背景色を変更する設定で、はまったときにmodenaを読みに読んで解決しました…)

stackoverflow.com

実際にプログラムを書いてみる。
使うコードはみんな大好き、oracleの解説ページ。

docs.oracle.com

setRowFactoryのところ以外は。 警告が出ているところをちょっと変えただけ。

   public void start(Stage stage) {
        Scene scene = new Scene(new Group());
        stage.setTitle("Table View Sample");
        stage.setWidth(450);
        stage.setHeight(500);

        final Label label = new Label("Address Book");
        label.setFont(new Font("Arial", 20));

        table.setEditable(true);

        table.setRowFactory(tableView -> {
            TableRow<Person> row = new TableRow<>();
            row.setStyle("-fx-text-background-color:red");

            return row;
        });

        TableColumn<Person, String> firstNameCol = new TableColumn<>("First Name");
        firstNameCol.setMinWidth(100);
        firstNameCol.setCellValueFactory(new PropertyValueFactory<>("firstName"));

        TableColumn<Person, String> lastNameCol = new TableColumn<>("Last Name");
        lastNameCol.setMinWidth(100);
        lastNameCol.setCellValueFactory(new PropertyValueFactory<>("lastName"));

        TableColumn<Person, String> emailCol = new TableColumn<>("Email");
        emailCol.setMinWidth(200);
        emailCol.setCellValueFactory(new PropertyValueFactory<>("email"));

        table.setItems(data);
        table.getColumns().addAll(firstNameCol, lastNameCol, emailCol);

        final VBox vbox = new VBox();
        vbox.setSpacing(5);
        vbox.setPadding(new Insets(10, 0, 0, 10));
        vbox.getChildren().addAll(label, table);

        ((Group) scene.getRoot()).getChildren().addAll(vbox);

        stage.setScene(scene);
        stage.show();
    }

f:id:takeda_san:20170406222047p:plain

重要なのが、ここ。

       table.setRowFactory(tableView -> {
            TableRow<Person> row = new TableRow<>();
            row.setStyle("-fx-text-background-color:red");

            return row;
        });

行の設定はtableのsetRowFactoryで行う。
カラムの中のセルの設定をcellFactoryで行うのと同じイメージ。
最初は全セルでモデルデータの値を頑張って取得して、文字色を変えようとしていたんだけど、
思えば行で設定してあげればよかったんですよね。
TableRowのsetFillでも、同じことができるかと思いきや、できない。
(-fx-text-fillでも同じ)

そのほうが、personのどれかの値が変わったときに文字色を変えたい!!!みたいなときに、updateItemをオーバーロードして更新ができる。
セルでやっていると実装の都合上、そのセル(カラム)に表示している値が更新されないとupdateItemが走らないので、実装が大変。

実際に書くとこんな感じだろうか。 イザベラさんの行だけを赤くする。

       table.setRowFactory(tableView -> {
            final TableRow<Person> row = new TableRow<Person>() {
                @Override
                protected void updateItem(Person person, boolean empty) {
                    super.updateItem(person, empty);

                    if (!empty) {
                        if ("Isabella".equals(person.firstName.getValue())) {
                            setStyle("-fx-text-background-color:red");
                        } else {
                            getStyleClass().remove("-fx-text-background-color:red");
                        }
                    }
                }
            };

            return row;
        });

スタイルの追加、削除の処理がちょっと怪しいがとりあえずは動く。

f:id:takeda_san:20170406222051p:plain

なんだかんだで、半日ほど悩んでいたが1行で事足りてしまった。
ちょっと複雑な気持ち。

プログラミングのための線形代数「1.1 ベクトルと空間」

やったこと

プログラミングのための線形代数「1.1 ベクトルと空間」を読む。

表紙の主な対象読者の記述にぐっときたので買ってしまいました。
『研究・仕事で信号処理なりデータ解析なりをやろうとして、その方面の本を読んだら、線形代数が出てきた。どうにもよくわからないから勉強したい(し直したい)けど、証明ばかりの数学の教科書や、わかった気にしかならない入門書しかなくて困る。』
素晴らしい。
空いた時間に少しずつ読んでいきます。

ベクトルって何?おいしいの?から解説してくれるので大変ありがたい。
また、整数と実数も怪しい私のような読者向けにコラムまで用意してくれる親切ぶりであった。
この節の内容は、大学でやった内容でまだ覚えている範囲。

随所で数学派の皆さんとRubyユーザにおびえてる記述があるのは何なんですかね。
聞きつけると肩パットのお兄さん達が、乗り込んでくるんですかね。

平均二乗誤差について少しだけ理解した話

前回のあらすじ

分類とラベルについて、今更理解した。

takeda-san.hatenablog.com

やったこと

統計学の入門書を読んでいる。

www.kyoritsu-pub.co.jp

要するにやる夫で学ぶ統計学的なものである。
半分ぐらいまで読んだが、今のところ躓くことなく読めている。
(題名については、漢字に長々とルビが振ってあるところが素敵だと思った)

以前に誤差関数に平均二乗誤差(MSE)を使ったサンプルプログラムを読んで、中途半端な理解のまま放置していた。

takeda-san.hatenablog.com

ちょっとばかり入門書で自信がついたので再び見てみよう。


\displaystyle MSE( \sum (t-o) ^ 2 )

相変わらず威圧感ある数式である。
サンプルプログラムの解説ページでは上記の表記であったが、わかりやすく書くと次のような数式らしい。


\displaystyle MSE(c) = \frac{1}{n} \sum_{i=1}^{n} (x_i - c) ^ 2

今回の場合、xが学習データの出力値(正解の値)、cがとあるパラメータでの出力値(予測値)と考えて、分散として求める。


\displaystyle \sum_{i=1}^{n} (x_i - c) ^ 2

それをデータの個数で割るとばらつきの平均値が求められる。
これを誤差の度合いとして小さくしていきましょうというのが、誤差関数に平均二乗誤差を使うということなのだろう。
前よりは納得。

しかし、courseraの機械学習コースでも、統計学の入門書でも分散の絶対値ではなく、2乗する意味については
「だって、こっちのほうが便利だろ?な。そうだろ?」
というばかりで一切解説してくれない。
業界のタブー的なものなのだろうか。

次回の予定

未実施

クラスタリングのサンプルプログラムを読む
Mavenのpomの読み方

実施中

統計学の入門書一冊読む
・courseraの機械学習の動画を見る
・Deep Learning Javaプログラミングを読む
・プログラミングのための線形代数を読む