せてぃーずノート

Javaのイベント参加レポートとかを書いたりします。

データのマスキングが気になったので調べてみた

セキュリティの要件を検討中、データのマスキングについて気になったので調べてみた。
具体的なシチュエーションとしてはこんな感じ。

  • システム導入先のユーザーと、そのシステムを構築・保守するSIer
  • SIerはテストや障害調査等でユーザーの個人情報含むデータ(顧客テーブルとか)が必要
  • 従来通りの氏名とか住所をマスキングすることは、個人情報保護法的にOKなのか

法律の解釈についてはあまり詳しくないので、間違っている箇所もあるかもしれないのでご容赦を。

匿名加工情報

個人情報保護法には「匿名加工情報」という言葉の定義があり、以下のように説明されていた。

・特定の個人を識別することができないように個人情報を加工して得られる個人に関する情報であって、当該個人情報を復元することができないようにしたものをいう。
・当該個人情報に含まれる記述等の一部を削除すること(当該一部の記述等を復元することのできる規則性を有しない方法により他の記述等に置き換えることを含む。)。
・当該個人情報に含まれる個人識別符号の全部を削除すること(当該個人識別符号を復元することのできる規則性を有しない方法により他の記述等に置き換えることを含む。)。

「個人識別符号」も定義されている。

・特定の個人の身体の一部の特徴を電子計算機の用に供するために変換した文字、番号、記号その他の符号であって、当該特定の個人を識別することができるもの
・個人に提供される役務の利用若しくは個人に販売される商品の購入に関し割り当てられ、又は個人に発行されるカードその他の書類に記載され、若しくは電磁的方式により記録された文字、番号、記号その他の符号であって、その利用者若しくは購入者又は発行を受ける者ごとに異なるものとなるように割り当てられ、又は記載され、若しくは記録されることにより、特定の利用者若しくは購入者又は発行を受ける者を識別することができるもの

特定の個人の身体の一部の特徴の例としては、顔写真とかが考えられる。
病院のカルテとかなら、病状や治療歴も含まれそう。
2つ目はクレジットカードや銀行口座の番号が該当する。
伝票番号とかは、他のデータと突き合わせれば購入した人がわかる可能性があるけど、この文には「他の情報と照合」という言葉が入っていないので許されるかもしれない。

ここまでのまとめ
  • マスキングして個人を特定できなくなったデータは個人情報保護法における「匿名加工情報」になる
  • 氏名や顔写真等は当然として、IDも削除しないといけない対象になる可能性がある

ID系についてはこんな感じ。

  • ICカードや領収証に記載されている人の目に触れる番号はマスキングが必須
  • システム内部でのみ使用しているサロゲートキーは許される(というか許されてほしい)

匿名加工情報の作成

これも法律に書いてあった。

個人情報取扱事業者は、匿名加工情報(匿名加工情報データベース等を構成するものに限る。以下同じ。)を作成するときは、特定の個人を識別すること及びその作成に用いる個人情報を復元することができないようにするために必要なものとして個人情報保護委員会規則で定める基準に従い、当該個人情報を加工しなければならない。
個人情報取扱事業者は、匿名加工情報を作成したときは、その作成に用いた個人情報から削除した記述等及び個人識別符号並びに前項の規定により行った加工の方法に関する情報の漏えいを防止するために必要なものとして個人情報保護委員会規則で定める基準に従い、これらの情報の安全管理のための措置を講じなければならない。
個人情報取扱事業者は、匿名加工情報を作成して当該匿名加工情報を第三者に提供するときは、個人情報保護委員会規則で定めるところにより、あらかじめ、第三者に提供される匿名加工情報に含まれる個人に関する情報の項目及びその提供の方法について公表するとともに、当該第三者に対して、当該提供に係る情報が匿名加工情報である旨を明示しなければならない。
個人情報取扱事業者は、匿名加工情報を作成したときは、個人情報保護委員会規則で定めるところにより、当該匿名加工情報に含まれる個人に関する情報の項目を公表しなければならない。 ・個人情報取扱事業者は、匿名加工情報を作成して自ら当該匿名加工情報を取り扱うに当たっては、当該匿名加工情報の作成に用いられた個人情報に係る本人を識別するために、当該匿名加工情報を他の情報と照合してはならない。
個人情報取扱事業者は、匿名加工情報を作成したときは、当該匿名加工情報の安全管理のために必要かつ適切な措置、当該匿名加工情報の作成その他の取扱いに関する苦情の処理その他の当該匿名加工情報の適正な取扱いを確保するために必要な措置を自ら講じ、かつ、当該措置の内容を公表するよう努めなければならない。

公表・・・?
えー、まとめると・・・

  • データをマスキングする時は、個人情報保護委員会規則で定める基準も考慮しないといけない
  • 加工の方法はバラしちゃだめ
  • 第三者に提供するときは公表しないといけない(!?)
    『みなさんこんにちわ、○○商社です。今回、わが社の顧客情報管理システムでトラブルが発生しました。つきましてはお客様のデータのうち氏名、住所を秘密にした顧客情報を、委託している××システムに提供します』とかプレスリリースとかに乗せろということ・・・なのか?
  • そもそも匿名加工情報を作った自体、公表しないといけない(!?)

なんかすごく面倒・・・。
少なくともシステムを開発・運用するSIerとの関係だと、法律通りの運用はされないのでは・・・。

JJUG CCC 2014 Fallに行ってきました

予定があって夕方に切り上げましたけど、今回は非常に内容が濃かったと思います。
とりあえず、参加したセッションの概要のまとめ。

K-1 基調講演1 : これからのJavaエンジニアの生きる道

技術の変化のための技術

クラウド

  • コンテナ型の仮想化ソフトDockerにより、クラウドプラットフォーム間の移動が簡単にできるようになると思われる。 ** より安く、サービスが充実した環境へ簡単に変えられる
  • Dockerで移動出来るようになったらクラウド事業者はどうなるか データロックインの方向に進むのではないか * データロックイン=データ活用のためのツールミドルウェア、ライブラリを充実。利用者が簡単に移動しないようにする。
  • 蓄積したデータを人工知能に利用する

時代はDockerっぽい。
データロックインという考え方は面白いかも。

人工知能

  • 人工知能に必要なものは認識、意思決定、行動
  • IBMのWatson。想定するユースケースはコールセンターで想定問答集や回答をサポートなど ** 「ロボットは東大に入れるか」という本が面白そう

  • 今、何故人工知能の話題が多いのか?
    ** データ、マシンパワーの増大により、認識やデータ解析の制度が向上。意思決定に使えるようになった。

  • 人工知能はデータが貯まるほど補正される関数
    ** 統計で問題をとくことは、理詰めでは説明できない。でも、なんとなくよく当たる。

  • Watsonは、音声認識→質問解析→検索→回答評価のプロセスで回答を導き出す。

  • 質問解析
    ** 問題からキーワードを抽出する。

  • 検索 ** キーワードをWebで検索し、回答の候補となる単語を抽出
  • 回答評価 ** 回答の候補を更に検索し、質問とマッチしているかを検索

Javaの今後

  • JVMは安定した大規模なWebサービスを運用可能 ** 今後は安定しているJVM上でJava言語以外の言語が動く流れが進むのでは

社会の変化

  • 価値にお金を払わない 例えばKickStarter。まだ製品化されていないのにお金を払う。 クオリティーじゃなく心に響く何かにお金を払っている

まとめ

  • 企業が人の成長を見られない状況。だからこそコミュニティは重要。

本当に人のつながりは大事だと思う。。。 というより、企業が人のつながりを軽視し過ぎで、コミュニティが特別じゃないというのが正直な思いかも。

私がTDDできないのはどう考えてもお前らが悪い!~エンタープライズJava開発でのTDD適用の勘所~

どうTDDするかについて?

チームの概要

  • BackBone.js+Spring MVC+Spring Batch+JPA
    テストケース3800ケース クライアント開発部隊とインテグレーター2社で1チーム *** 初めて顔を合わせるメンバーが多い。手探り。
  • ペア組んでユニットテストコーチング。

進め方

  • インテグレーションの中で実装とテストが完結していればOK。
    ** テストがあることのメリットを感じてもらう
  • フェイルファストしてないユニットテストは、フェイルファストしているテストと比べて信頼性を欠く。
  • 自動でないテストを重視する
    ** ユニットテストから漏れるバグが有ることを知っておく
  • コントローラーとサービスを優先的にテスト テストで100%を目指さない。
    再現性がある、独立しているが重要。
    *** それがないとCIに乗せられない

  • 技術的負債は改善サイクルに含める ** Tryをちゃんとタスク化する

  • 今のチームは問題を指摘したら次のスプリントに乗せてくれる。
    ** チームの信頼感重要

スローテスト

  • スローテストによる開発リズムの悪化はプロジェクトの死因
  • データベースを使うテストは遅い問題 データベースを使うことが遅いなら、データベースはプロダクトに使えない テスト実行時間より、テストデータのメンテナンスがスローテストの原因 *** エクセルでデータ管理の限界
  • データベースのアサートはテーブル全体に行う ** 差分をとってアサート出来るようにDBユニットをカスタマイズ
  • データベースマイグレーションはTDDを実施するのに必須

コントローラー層のテスト

  • End to Endに近い条件で。
  • DIしたオブジェクトをモックにすると、コンテナ内のオブジェクトが汚染される。
    ** @Afterでモックオブジェクトを取り除く

リグレッションテスト

デプロイの自動化

  • ServerSpecでデプロイスプリクトのコードを検証

なぜTDDするのか

  • 「もううんざりです。何も改善できません。」問題
  • TDDを導入するために必要なのはチームを作ること スキルの有無、キャリアの長短を人を測る尺度にしない
    「新人だから知らないと思うけど」という考え方は間違い ** IT技術者各人の背景を尊重すること重要

Spring Boot + Doma + AngularJSで作るERP(統合基幹業務システム)

プロダクトの歴史

2007年 seasar2、IE6と7をサポート。

  • IE8で動かない問題
  • 時代遅れ感の出てきたUI
  • リッチなWebサイトが増えて顧客の目が肥えてきた
  • 他のRESTAPIとの連携
  • 改修より作りなおすことを選択

Java EE 6 作成

  • PrimeFaces、JPAを利用 ** Seasar2時代もJSFを利用していたため
  • どうもしっくりこない。2サブシステムで終了

SpringMVC

  • 開発をリナックスで行う 文字コード、改行コード、パス区切り文字、レイアウト崩れ
    開発環境はVagrantで配布

  • Doma2 S2DAOを利用していたので、移行が楽だった SQLをごりごり書きたい派にはおすすめ。
    ** 依存ライブラリがない点もいい

  • Angular.js bootstrapのみを使用。ライブラリは自分で作成。
    JSFより軽快(当社比) ** バージョンアップで後方互換性が保たれない。

  • Spring開発にTerasolnaのガイドラインが役にたった

  • Angularは業務で使っても大丈夫 動かなくなったらフロントだけ作りなおせばいいという割り切り 当然コストがかかる
    一般的なシステムの償却期間は5年 フロントFrameworkの追従の予算が取れるかどうか。
    ** とれないならJSFのように一度作れば動き続けるものがよいのでは

  • 標準だから、流行ってるからじゃなく、きちんと検証して自分たちに合うものを選ぶ

QA

  • 3つのアーキテクチャの連携は? ** 認証はそれぞれ独立。連携する部分は少ない。

Java EE の新たな旅立ち : Java EE 8 へ向かって

Java EE8の具体的な内容について
現時点でのSnapshotのため、コードは変わる可能性あり

Java EE 8について

  • 業界のトレンドを観察
  • HTML5クラウド対応、簡単開発がテーマ

JSONB

  • JAXBとおなじ感覚で使える

JSONP

  • JSONPointer、JSONPatch、クエリに対するラムダ式を追加予定 JSONPointerは特定の値を参照するための標準(RFC)の構文 JSONPatchもRFCに定義されている
    JSONで記述したパッチを利用して更新 ラムダ式用にJSONCollectorクラスを提供
    ** toJsonArrayのような終端処理が出来る

SSE(サーバセンドイベント)

  • HTTP標準。実装をどこでやるかはまだ未定。 ** JAX-RSで対応するのが今のところ有望

ActionベースMVC

  • コントローラーの部分が未定。
    ** JAX-RSでやるのか、新しく追加するのか

  • Viewの部分はJSPかFaceletを選択できる ** Faceletの場合、Formにアクションを追加。

http2.0対応

  • Request/Responseの多重化、Streamの優先順位付け、ServerPush ** 今のServletAPIでは、Request/Responseの多重化に対応できない

CDIの適用範囲拡大

  • JSRは365
  • JavaEE以外でも使用できるようになる

これはちょっと嬉しい。

CDIのモジュール化

  • 多くの機能が追加されることによる肥大化の回避。
    ** DIのみ、CDIイベントのみ、フルセットから選択

EJBの教訓かな。

他機能との連携強化

  • JMSとの連携 ** MDBの実装が不要に

セキュリティインターセプタ

サンプルコード見た限り、ごちゃごちゃしすぎて使いづらそう。

仕様削減(pruning)

  • EJB2.Xのクライアント

まぁ、これはなくなっていいと思う。

JMX

  • JSR77にRESTインターフェースを追加
    ** JMXがサーバ実装に非依存

RESTでアクセスできるのはいいと思うけど、各サーバは独自実装捨てないといけなくなるから対応が大変そう。

セキュリティ

Javaエンジニアのためのアーキテクト講座

システム開発の現状

  • 「アプリケーションをいかによく作るか」から、「ITサービスをいかに良く運営するか 」への変化
  • 静的な仕様から作る→開発
  • 動的なフィードバックに基づく活動→運営 ** Web業界が先駆者
  • デジタル化 ** テクノロジーが社会に関わる
  • 仕様書に従って安全なコードを書けばいい時代は終わる

アーキテクチャの役割

  • 価値は利用者の体験によって定義される
    ** 一度リリースされたら終わりではない
  • フィードバックに対する持続的な成長
  • これら全体をデザインするアーキテクチャが必要 ** 家を建てる例

    家族がそれぞれ家のパーツを考える。それを形にしてもきちんと整合性が取れたものにならない。
    整合性をとり、かつ地震が来ても大丈夫なシステム。
    フィードバックを受け続け、継続的に保証する。

  • 利用者の動線、時期と作業、それに対応するだけの並行処理、トランザクション増加、負荷を分散させるためのclass分割、作るための要因と手法、KPIとしての評価

必要とされるスキル

  • TOGAFの全部が必要
    ** だけど、全部をやる必要ない。
  • 品質モデルとかは知ってないとダメ。
  • フレームワークの構成とかを考えるだけなのはアーキテクトじゃない。

設計の進め方

  • マイクロサービスアーキテクチャ ** 個々のサービス→データ、ガバナンス、手法も独立
  • 個々のサービスは個々のチームによって開発、運用 ** 責任も各チーム

  • マイクロサービスアーキテクチャの考え方はある ECサイト
    商品登録 カート 決済 ** 配送

異なるドメインとして定義

  • ユーザによって役割が異なる
    ユーザによって利用されるサイクルが違う
    * 変化の境界線
  • それぞれのサービスごとに利用者とサイクルが異なる。
  • ドメインを分割しつつも非機能も考えないといけない。
    ** ECサイトの例。決済のASPダウンしてるから買わせないはダメ

QA

  • Q:アーキテクトが役割を理解してもらうためには? ** A:正しいと思う行動をする。それでもダメなら・・・。
  • Q:プロマネとかぶる? ** A:計画をたてる人がアーキテクト、プロマネは計画を進める。
    IBMはアーキテクトが仕事をした後じゃないとプロマネは仕事ができていないと言われている。

  • Q:経営者は含まれないのか? ** A:経営者はざっくりしか言わないし、言うことも変わる。適当に受け流す。

JJUG ナイトセミナー「WildFly 8 ローンチ記念」行ってきました

久しぶりのJavaEEということで行ってきました。
やっぱりEEはいいですねー。

リンク

DoorKeeper

【東京】JJUG ナイトセミナー 「WildFly 8 ローンチ記念」Red Hat共同開催 - 日本Javaユーザーグループ | Doorkeeper

発表資料はこちら。

What’s new in WildFly 8 ?

wildfly-deck/deck/slides.html at master · arun-gupta/wildfly-deck · GitHub

Undertow

次世代Webコンテナ Undertowについて

WildFlyについて

What’s new in WildFly 8 ?はJavaEEの有名人、Arun Guptaさんが世界中でやったセッション。
日本でもやる予定だったけど、「日本人がやればいいんじゃね?」ということで今回のセッションが開催されることになったようです。

WildFlyって何?

Java EE 7準拠のアプリケーションサーバです。

昔はJBossASという名前だったけど、JBossから始まるプロダクトが非常に多く、ぐぐらビリティが悪いから名前を変えたそうです。
なお、RedHatが出してる有償サポート版であるJBossEAPは、専門の検索サイトが有るらしいので問題はないそうです。
WildFlyEAPにはならないっぽい。

特徴は早いこと。
デモだと1.5秒で起動しています。
載せてるアプリにもよるけど、TomcatとゴテゴテSpringより起動は早そうです。

また、非常に開発者フレンドリーらしいです。

どこが変わったの?

  • サーブレットの部分をTomcatベースのものから高速なWebサーバーのUndertowに変更
  • WebSocketを使用することで、使用するポートを5から2に減らした
  • ロールを使用したアクセス管理・・・
  • 自動パッチ機能
    Zipファイルをダウンロードしてアップデートすることが出来ます。
    更に元のバージョンに戻すことも可能。

他にもこんな機能が

  • JDK8に対応
    ただし、まだ対応版はJavaEEのコンパチビリティテストを通っていない
    コンパチビリティテストの方がJava8に対応するのを待つらしい
  • RESTEasy3はJerseyよりも優秀らしい
  • Hibernate searchで全文検索出来るようになった
    使いどころとしては、不動産の検索とか。デフォルトで入っているのがスモイ。
  • デプロイメントごとにセキュリティの設定が変えられる
    クラウド環境で使うことを想定しているらしい。
  • 元からクラスタリングテクノロジーが強い
  • EJB2.1のEntityBean、JAX-RPC、JSR88をバッサリとカット
  • クラウド対応
    OpenShiftやCloudBeeなど。
  • 有償サポートであるEAPのJavaEE7対応版はWildFly9がベースになる。
    WildFlyは来年の頭に出る予定なので、EAPは来年の中頃くらい。
    楽しみに待ちましょう。
    (そのころはJavaEE8の話題で持ちきりな予感もする・・・)

Undertowのお話

Undertowとは?

  • Webサーブレットコンテナ。2012/7に初コミットの若いコンテナ。
  • パフォーマンスが凄くいい。
  • XNIOというライブラリを使用。
  • とにかく軽い。ヒープに展開しても10MBくらい。
  • JBoss7まではTomcatの強化版。
    強化版はパフォーマンス向上、クラスタリングの独自実装。
    Struts祭りで被害なし。
  • そんな強化猫から乗り換えた理由は、Webの発展についていくのが難しくなったから。

特徴

  • ワーカー、リスナー、ハンドラーから構成。
  • Requestを受け付けるとハンドラを呼ぶ。
    ハンドラを小さい処理を記述し、それをチェーンしていく方式。
    サーブレットフィルターみたいなイメージかも
  • Wildflyで動くときはハンドラーを自動で登録してくれる。

その他

  • 設定周りがわかりやすかも。XML地獄じゃない。
  • 開発者がフレンドリーで、機能をリクエストすると取り込んでもらえるかも
    アクセスログはそれで追加されたらしいです。

まとめ

GlassFishと比べて勢いがある印象。
やっぱり有償サポートが控えてるっていうのが強みな気がする。

Undertowは単体で使うのはちょっと難しそうですけど、WildFlyに組み込まれている分には問題なさそう。
Tomcat以外の選択肢が増えるのはとてもいいことだと思います。

JSFさんの空気っぷり・・・。

JavaDayTokyo2014に行ってきた

去る5月22日に行われたJavaDayTokyoに行ってきました。
去年の秋葉原に引き続き、2年連続の参加です。
参加して思ったことを書き連ねてみます。

日本Oracleの本気度アップ

f:id:setys:20140522092153j:plain

秋葉原UDXから品川プリンスに変更になり、会場に余裕が出来ました。
去年はすし詰め状態だった基調講演もゆったり聞くことが出来ました。
椅子も柔らかく座り心地もよいものが用意され、腰痛持ちの自分でも安心して参加出来ました。

さらに待望のJavaSE8日本語ドキュメントのリリースも発表。
SE7の日本語ドキュメントが去年のJavaDayTokyoだった気がするので、それに比べれば非常に早いリリースだと思います。
これがきっかけで、日本でもJava8が一気に浸透していくのではないでしょうか。(願望)

IoT重点の基調講演

基調講演の50%以上はIoT関連のものでした。
驚いたことに、本家JavaOneの基調講演で登場したDukePadやチェスロボットが登場したこと。
Oracleが日本の市場を重視していることが伺えます。
わざわざアメリカに行かなくても日本でOK、ではなくいつかは本家でお披露目の瞬間でみたいです。

f:id:setys:20140522112443j:plain

f:id:setys:20140522115338j:plain

マインドストームDukeも登場し、会場はとても盛り上がっていました。
日本からもNECのパペロが参戦し、流暢なお喋りを披露してくれました。

MindstormやRaspberry Piのような小さなデバイスでほぼJavaSEのコードが動くことは、開発者が今まで持っているスキルでできることを広げてくれる夢のある話です。
だってこちらが何もしなくても出来ることが広がっていくんんですよ?
Lambdaをマスターしているうちに、ロボットも動かせるようになるなんてすごい時代になったものだと思います。

端末の性能も向上していけば、できることはさらに増えていくのではないでしょうか。

その反面EEは・・・

『C-1 Java SE 8時代のJava EE 7アプリケーション開発』では、MindstormとJava EE7を組み合わせたデモが披露されました。
ブラウザとGlassfishはWebSocketで接続、GlassfishとMindstormの間もWebsocketで接続し、JavaSEとJavaEEだけでもブラウザからリモートコントロールするアプリを作れることを示してくれました。
今後、エンタープライズなWebアプリしか作ったことがない人でも、IoTを使いこなせる様になるというのは開発者にとって嬉しい事です。

ここまで出来るようになっているにも関わらず、JavaEE7準拠のアプリケーションサーバーが遅れていることが非常にもったいない。
Glassfishは有償サポートがなくなった上、4.0.1が今年のJavaOneにようやくリリース(できればいいなぁ)という状況。
WebLogicは今年中は厳しい。
WASが辛うじて今年間に合いそう?
日本のベンダーはどうなってる?
こんな状況だと、せっかくのいいものが個人で楽しんだり教育での使用にとどまってしまいます。
Javaユーザーが多いエンタープライズな方面でも使えるようになってほしいです。

IoTの端末部分がいろいろ進化しても、肝心のクラウドで使うものが遅れてちゃあ・・・。 Oracleさんもそこんとこわかっているとは思いますので、今年のJavaOneでの巻き返しに期待です。

とにかくLambdaだ!

あとはJavaSE8と言うよりLambda祭り。
Lambdaは難しそうに見えても文法の仕組みを知ってしまえば書くのは簡単。
でも奥が深くて使いこなすのは難しい。
そして、使いこなせれば強力な武器になる魅力的な機能です。

Lambdaについては使いこんで慣れることが肝心だと思います。
Lambda100%セッションとしてはA-4を聞きましたが、イキナリ聞いただけではほとんど理解できないんじゃないかなと思います。
A-2の続きだったようですが、Lambda知識0でA-2→A-4と聞いてついてこれた人はなかなか少ないのではないかと。
初めてのLambdaとか入門Lambdaというイベントは、今年一杯で終わりそうな気もするので、なるべく早いうちにJava8に慣れておくことが重要です。

あとは、日本語APIリファレンスが出たので、StreamAPIはちゃんと読んでおこうと思います。 注釈に重要な情報が大量に書いてありました。
特にparallel使って見るときは読む必要があります。

その他もろもろ

コミュニティ寄りの人もスーツな人もどちらも楽しめるバランスになっている良いイベントだったと思います。
IoT関連の展示も面白く、Raspberry Pi、Mindstormのいずれも完売する人気っぷり。
Mindstormは欲しかったけど、10万ドル、ぽんっと出してくれるほどお財布さんが優しくなかったので泣く泣く諦めました。
ゴールデンウィークの月に行うのが悪いと思います。

それでも重箱の隅をつつくように注文をつけるのであれば、遠路はるばるお越しいただいた人向けに荷物の預かり所(もしくはその案内)があったほうがいいとは思います。
荷物が多いとかさばりますし、セッション聞くのも大変です。
あの人混みでキャリーバックを引いてる人がいて、案の定轢かれました。。。

forループ殺すべし。慈悲はない。

うん。言ってみたかっただけなんだ。

JJUG CCC 2014春に行ってきました。
基調講演の『foreach書いたら負け!for禁止!』という言葉のインパクトが強すぎです。
その後のセッションのデモでforが出てくるとツッコミが入っていたくらいです。

とりあえず、マケグミ・サラリマンにならないようにforを潰す練習をしてみました。

一時変数を使ったループの置き換え

一時変数を使ったループはこんな感じで置き換えればよさそうです。

for (int i = 0; i < 100; i++) {
    // 何か処理をする!
}

これをLambdaにしてみるとこんな感じ。

IntStream.range(0, 100).forEach(i -> ここに処理を書く!);

1行で書けるのが素晴らし。

条件に適合したらループを抜けるケース

いきなり自信なくなります。
動いているのは確認してますけど、もっと良いやり方があるとかもしれないので・・・。

例としてはListを先頭から検索していき、条件に該当するものが見つかったらループを抜けるケースです。

for (int i = 0; i < 100; i++) {
     if (condition) {
        // 何か処理をする!
        break;
     }
}

forの方はだんだんウザくなってきました。
これをLambdaで書いてみると、こんな感じになります。

IntStream.range(1, 100).filter(i -> condition).findFirst().ifPresent(i -> 処理を書こう);

filterメソッドで条件を指定し、findFirstメソッドで条件に一致する最初の値に対して処理をおこないます。
条件に該当する数値がない場合は、処理が呼び出されません。
例外じゃないです。

Lambdaにすると読みやすくなったといえます。
それに加え、先頭から要素を探す残念処理を簡単にパラレルで実行できたりもシマス。

IntStream.range(1, 100000).parallel().filter(i -> condition).以下略

途中にparallelメソッドを挟むことで処理が並列で行われるので、条件に一致するものを見つけるまでの時間が早くなります。

決められた件数だけを処理するパターン

リストの最後に到達するか一定の件数を超えたら処理を終了するパターンです。
for文で書くとこんな感じ。

int count = 0;
for (int i = 0; i < 100; i++) {
     if (condition) {
        // 何か処理をする!
        count++;
        if (count == 10) {
            // 10件処理したら終わる
            break;
        }
     }
}

うんざりするようなソースですが、Lambdaならこんなに簡単に書けます。

IntStream.range(1, 100).filter(i -> condition).limit(10).forEach(処理をする!);

limitは上限を設定するメソッドで、条件に該当する要素に対して10件処理をしたら終了になります。
forでやっている時のような一時変数でカウントする必要がないのでスッキリします。
こちらも処理がスレッドセーフなら、parallelにして処理時間を短縮することが出来ると思います。

今日やったことまとめ

一時変数forループもLambdaにすると可読性も上がっていい感じ。
IntStreamには今回使ったfindFirstやlimitだけじゃなく、distinctとかmaxといったフィルタリングするのに便利なメソッドが多いので複雑なループでも大丈夫。

Lambdaこわいにならないように準備しておくのが肝心だと思います。
あとは、Java8を仕事で使う政治的根回しをすることも重要です・・・。
なんで、来月から始まるJava開発がJava6なんですかね、某大手ベンダー=サン・・・

関数型インターフェースで気になったことを試してみた

関数型インターフェースとは?

ざっくり言うと、メソッドが1つだけ定義されたインターフェース。

関数型にならないケース

メソッド1つだけと言っても、defaultやstaticは対象外。
なので、defaultメソッドだけ持ったインターフェースは関数インターフェースと呼べない。

@FunctionalInterface
public interface A {
    default public int onlyMethod(int value) {
        return origin * 2;
    };
}

エラーメッセージはこんな感じ。

予期しない@FunctionalInterface注釈
Aは機能インタフェースではありません
  インタフェース Aで抽象メソッドが見つかりません

てか、関数型インターフェースって名前じゃないのか!
機械翻訳な気もするけど、Oracle公式は機能インターフェースなんですかねぇ。

関数型インターフェースと継承

関数型インターフェースを継承しても、メソッドが1つだけなら関数型インターフェースを名乗れる。
使いドコロは・・・ないと思うけど。

@FunctionalInterface
public interface A {
    int onlyMethod(int value);
}

@FunctionalInterface
public interface B extends A{
      // コンパイルエラーにならない。
}

当然ですけど、default修飾子付きのメソッドでオーバーライドするとコンパイルエラーです。
エラーメッセージは最初と同じで抽象メソッドが見つからないという内容です。

@FunctionalInterface
public interface C extends A{
    @Override
    default int onlyMethod(int value) {
        return 0;
    };
}

なお、@FunctionalInterfaceを外せばコンパイルは通ります。
それによって、インターフェースの抽象メソッドをインターフェースが実装するという謎なインターフェースが出来上がります。

継承(逆の場合)

関数型ではないインターフェースを継承して無理やり関数型にしてしまう。

public interface A {
   default int onlyMethod(int value) {
       return 0;
   };
}

@FunctionalInterface
public interface B extends A{
    int onlyMethod(int value);
}

デフォルトの実装を全く無視する荒業。
使い道あるかは知らぬ・・・。

多重継承

複数のインターフェースを継承した場合のパターンも試してみました。
まずはコンパイルエラーにならないパターン。

@FunctionalInterface
public interface A1 {
    int onlyMethod(int value);
}

@FunctionalInterface
public interface A2 {
    int onlyMethod(int value);
}

@FunctionalInterface
public interface B extends A1, A2 {
      // コンパイルエラーにならない。
}

当然、継承するインターフェースのメソッドの定義が違えばコンパイルエラーになります。

@FunctionalInterface
public interface A1 {
    int mainMethod(int value);
}

@FunctionalInterface
public interface A2 {
    int subMethod(int value);
}

@FunctionalInterface
public interface B extends A1, A2 {
      // これはコンパイルエラー。
}

ちなみにエラーメッセージはこんな感じ。

予期しない@FunctionalInterface注釈
Bは機能インタフェースではありません
インタフェース Bで複数のオーバーライドしない抽象メソッドが見つかりました

この場合、どちらかのメソッドを実装すればBを関数型インターフェースにすることができます。

@FunctionalInterface
public interface B extends A1 , A2 {
    @Override
    default int subMethod(int value) {
        return 1;
    };
}

やっぱり使いドコロが無さそうですが、あえて使うならこんな感じだと思います。

@FunctionalInterface
public interface C extends A , B{
    @Override
    default int subMethod(int value) {
        // デフォルトと言いつつ実装を強要してみる
        throw new UnsupportedOperationException();
    };
}

ここまでして関数型インターフェースを作りたい男の人って・・・。

まとめ

Lambdaに付随して言語仕様がガッツリ変わっているおかげで、インターフェース周りで色々出来て面白いです。
ただ、きちんと規約決めておかないとインターフェースに実装メソッドが大量発生したりstaticメソッドだらけになってカオスなものが出来上がる予感もします。。。

Java8時代の文字列結合のまとめが気になったので試してみた

元ネタはこちら

Java8時代の文字列連結まとめ - きしだのはてな

だいぶ今更感がありますけど、気になったことが合ったので試してみました。

  • 気になったこと1
    データ量が多くなったら急に性能が落ちるケースってあるのか?

  • 気になったこと2
    一応SIer所属なので、「漢は黙ってStringBuffer」も比較対象に加えたい。

というわけで、きしださんの作ったソースのコピペ をベースに、StringBufferで結合する素敵メソッドを追加。
それに対して文字列リストの要素数を1倍、10倍、100倍のケースで測ってみました。

まずはオリジナルの要素数で。

stringJoin:1812ms
stringBuilderJoinMem:958ms
stringArrayJoining:686ms
charBufferJoin:773ms
stringBufferJoin:1240ms

これはきしださんの結果と大体一致しています。
String#joinを使われるよりは、StringBufferの方がマシというところでしょうか。

次に文字列の要素数を10倍にして実行。
予想ではだいたい10倍位の時間になるはずですが。。。

stringJoin:18484ms
stringBuilderJoinMem:10775ms
stringArrayJoining:8595ms
charBufferJoin:13221ms
stringBufferJoin:12630ms

アイエエエ!?CharBufferナンデ!?
素数が10倍になったら処理時間が20倍くらいになってます。
まさかのStringBufferよりも遅いという結末。

思い当たるフシとして、allocateのサイズが割りと適当なこと。
そこで、allocateの引数を90000(適当な数値)結合した文字列の長さに合わせた79995バイトに変更してみました。

CharBuffer buffer = CharBuffer.allocate(79995);

再測定した結果はこんな感じです。

stringJoin:18971ms
stringBuilderJoinMem:10594ms
stringArrayJoining:8212ms
charBufferJoin:12023ms
stringBufferJoin:12849ms

StringBufferより辛うじて早いけれど・・・という感じです。
ちなみにその後に行った100倍の結果はこちら。

stringJoin:197357ms
stringBuilderJoinMem:111888ms
stringArrayJoining:89730ms
charBufferJoin:129791ms
stringBufferJoin:132432ms

こちらは比較的予想通りの結果です。
CharBufferも前回のリミット見直しのおかげでStringBufferより早いです。

まとめ

試してみたなりのまとめです。

  • カツカツな性能が求められていない限り、StringBuilderが安定。
  • CharBufferのリミットはしっかり設定しよう。
    本来は文字列結合だけの目的で使うクラスじゃないのでしょうが・・・。
  • あれ、Java8の要素があまりないよ?

ま、まぁ、+演算子で結合というような事をしない限りは、文字列結合の速度で問題にはならない気がします。

補足

ByteBufferは使うけど、CharBuffer使ったの初めてかも・・・。