SlideShare a Scribd company logo
1 of 253
Download to read offline
Brand new Data Processing
2014/7/12 15:30-16:30
Shinya Yoshida(@bitter_fox)
関西Javaエンジニアの会スペシャル!Java 8リリース
StreamAPI
2
Who are you?
● 吉田真也(@bitter_fox)
● 立命館大学 情報理工学部 情報システム学科
– 高性能計算機ソフトウェアシステム研究室
● 立命館コンピュータクラブ(RCC) 執行委員長
(代表)
● http://www.rcc.ritsumei.ac.jp/
3
OSC 2014 Kyoto
4
OSC 2014 Kyoto
5
HashTag
#kanjava
6
JavaSE8
7
JavaSE8
Revolution
8
JavaSE8
Revolution
JavaSE5以来
(2004年)
9
JavaSE8
Revolution
JavaSE5以来
(2004年)
10年
ぶり
10
JavaSE8
Data Processing
Revolution
JavaSE5以来
(2004年)
10年
ぶり
11
JavaSE8
Project Lambda
Revolution
JavaSE5以来
(2004年)
10年
ぶり
12
Project Lambda
● 並列処理を容易に書ける様に増強
– ライブラリ
– 言語
● StreamAPI(!=IOStream)の導入
● ラムダ式の導入
13
Why Project Lambda?
14
マルチコアCPU
15
マルチコアCPU
● CPU(ハード)のパラダイムシフト
– クロック数はそのまま
コア(数)を増やす
– 並列処理
● ソフトウェアにもパラダイムシフト
● 並列プログラミングにしないと性能をフルに利用で
きない
– アムダールの法則
16
アムダールの法則
90% 10%
90%
80% 20%
80%
5
%
1コア
1コア
∞コア
4コア
逐次処理 並列処理
17
現代的なアーキテクチャ
少しでも多くの部分で並列処理
18
並列処理ライブラリの歴史
java.lang.Thread
扱いが難しかった/大きな粒度
JavaSE5(J2SE 5.0)
Concurrency Utilities(java.util.concurrent.*)
簡単化/大きな粒度
JavaSE7
Fork/Join Framework
小さな粒度/やや難
19
ProjectLambda発足当時(JavaSE6〜JavaSE7)
小さな粒度向けのライブラリが無かった
JavaSE7後
小さな粒度向けのライブラリがあるものの使いづらい
20
Fork/Join Frameworkを利用した
並列データ処理APIを
21
コアライブラリ
Project Lambda
22
ライブラリでは不十分
new Runnable(){
public void run(){
// proc
}
}
● 処理を分けるだけで5行
● いくらライブラリが良くても・・・
● 言語的に解決する必要がある
23
コアライブラリ
ラムダ式
メソッド参照
型推論の強化
実質的にfinal
交差型キャスト
Project Lambda
24
ライブラリの増強
● 一度公開されたインターフェース
– 変更を加えにくい
– メソッド追加
● 具象クラスが追随する必要がある
– 実装の提供
25
コアライブラリ
ラムダ式
メソッド参照
型推論の強化
実質的にfinal
交差型キャスト
defaultメソッド
stat. Intf. メソッド
Project Lambda
26
徹底解説!Project Lambdaのすべて
● 言語特徴のより詳細な情報
● On Slideshare
– http://www.slideshare.net/bitter_fox/jjug-ccc-2013-fa
ul
– http://www.slideshare.net/bitter_fox/java8-launch
– http://www.slideshare.net/bitter_fox/ss-35882498
– ↑最新版
27
コアライブラリ
ラムダ式
メソッド参照
型推論の強化
実質的にfinal
交差型キャスト
defaultメソッド
stat. Intf. メソッド
Project Lambda
28
コアライブラリ
Project Lambdaに関連
defaultメソッド
Collections
Framework
StreamAPIOptional
IO/NIO
Concurrensy
Utilities
Logging
Etc...
java.utill.function
29
コアライブラリ
Project Lambdaに関連
defaultメソッド
Collections
Framework
StreamAPIOptional
IO/NIO
Concurrensy
Utilities
Logging
Etc...
java.utill.function
Enhancement Collection Framework
● Iterable
– #forEach
● Collection
– #removeIf
● List
– #replaceAll
– #sort
● Map
– #forEach
– #compute
● IfAbsent
● IfPresent
– #getOrDefault
– #merge
– #replace
● All
– #remove
– #putIfAbsent
Enhancement Collection Framework
● Iterable
– #forEach
● Collection
– #removeIf
● List
– #replaceAll
– #sort
● Map
– #forEach
– #compute
● IfAbsent
● IfPresent
– #getOrDefault
– #merge
– #replace
● All
– #remove
– #putIfAbsent
Iterable#forEach
for (String s : strings) {
System.out.println(s);
}
外部イテレーション
● イテレーションをユーザコードが行う
● for文,while文
● 並列化が困難
– ユーザコードの大幅な変更が必要
Iterable#forEach
for (String s : strings) {
System.out.println(s);
}
strings.forEach(new Consumer<String>() {
public void apply(String s) {
System.out.println(s);
}
});
内部イテレーション
● イテレーションがライブラリの中に隠れてる
● イテレーション以外の処理を受け取る
● 並列化が容易
– イテレーションの方法を簡単に切り替えられる
– ユーザコードの変更は最小限
内部イテレーション
● イテレーションがライブラリの中に隠れてる
● イテレーション以外の処理を受け取る
● 並列化が容易
– イテレーションの方法を簡単に切り替えられる
– ユーザコードの変更は最小限
Iterable#forEach
public void forEach(Consumer<T> c) {
for (T t : this) {
c.apply(t);
}
}
並列化のイメージ
public void forEach(Consumer<T> c) {
if (isParallel()) {
this.parallelForEach(c);
} else {
this.sequentialForEach(c);
}
}
Collection#removeIf
● for (Iterator<String> i = strings.iterator();
i.hasNext(); ) {
String s = i.next();
if (s.length() > 10) {
i.remove();
}
}
Collection#removeIf
strings.removeIf(new Predicate<String>() {
public boolean test(String s) {
return s.length() > 10;
}
});
Map#computeIfAbsent
if (map.get(dep) == null) {
map.put(dep, new ArrayList<Emp>());
}
Map#computeIfAbsent
map.computeIfAbsent(name,
new Function<String, List<Emp>>() {
public List<Emp> apply(String s) {
return new ArrayList<>();
}
});
● イテレーションではないが知っていると便利
Collection拡張の不満
● 内部イテレーションのほうが長い
– 特に縦に長い
● インターフェースの拡張性が低い
– インターフェースへのメソッド追加
– 追加されたメソッドの実装を追加しないといけない
Collection拡張の不満
● 内部イテレーションのほうが長い
– 特に縦に長い
– ラムダ式・メソッド参照で解決
● インターフェースの拡張性が低い
– インターフェースへのメソッド追加
– 追加されたメソッドの実装を追加しないといけない
– デフォルトメソッドで解決
問題点
● 内部イテレーションのほうが長い
– 特に縦に長い
– ラムダ式・メソッド参照で解決
● インターフェースの拡張性が低い
– インターフェースへのメソッド追加
– 追加されたメソッドの実装を追加しないといけない
– デフォルトメソッドで解決
内部イテレーションのほうが長い
● 処理の分離が長い
– 匿名クラス
strings.forEach(new Consumer<String>() {
public void apply(String s) {
System.out.println(s);
}
});
内部イテレーションのほうが長い
● 処理の分離が長い
– 匿名クラス
strings.forEach(new Consumer<String>() {
public void apply(String s) {
System.out.println(s);
}
});
実装するべきメソッドが一つ
内部イテレーションのほうが長い
● 処理の分離が長い
– 匿名クラス
strings.forEach(new Consumer<String>() {
public void apply(String s) {
System.out.println(s);
}
});
実装するべきメソッドが一つ
インターフェース
49
● 実装するべきメソッド(抽象メソッド)が一つ
● インターフェース
– java.lang.Runnable
– java.lang.Callable
– java.nio.file.PathMatcher
– java.awt.event.ActionListener
– java.swing.event.ChangeListner
– ...
50
関数型インターフェース
● 実装するべきメソッド(抽象メソッド)が一つ
● インターフェース
– java.lang.Runnable
– java.lang.Callable
– java.nio.file.PathMatcher
– java.awt.event.ActionListener
– java.swing.event.ChangeListner
– ...
51
関数型インターフェース
● 処理を分けるのに十分
● ライブラリの多くで利用されている
● 実装&インスタンス化する構文としてラムダ式
– 匿名クラスに代わる構文
52
関数型インターフェース?
interface F {
void f();
}
53
関数型インターフェース?
interface F {
void f();
}
● Yes!
54
関数型インターフェース?
interface F {
boolean equals(Object o);
}
55
関数型インターフェース?
interface F {
boolean equals(Object o);
}
● No!
● equalsはObjectクラスで定義されている
– インターフェースにおいて暗黙的なメソッド
抽象メソッドは0個
56
関数型インターフェース?
interface F {
Object clone();
}
57
関数型インターフェース?
interface F {
Object clone();
}
● Yes!
● cloneもObjectクラスで宣言されているが
protected
– Fではpublicで再宣言されている
58
関数型インターフェース(JLS9.8)
A functional interface is an interface that has just one abstract method, and thus represents a single function contract. (In some cases, this "single" method may take the form of multiple
abstract methods with override-equivalent signatures (8.4.2) inherited from superinterfaces; in this case, the inherited methods logically represent a single method.)
More precisely, for interface I, let M be the set of abstract methods that are members of I but that do not have the same signature as any public instance method of the class Object. Then I is
a functional interface if there exists a method m in M for which the following conditions hold:
The signature of m is a subsignature (8.4.2) of every method's signature in M.
m is return-type-substitutable (8.4.5) for every method in M.
In addition to the usual process of creating an interface instance by declaring (8.1) and instantiating (15.9) a class, instances of functional interfaces can be created with lambda expressions
(15.27), method references (15.28), or constructor references.
The function descriptor of a functional interface I is a method type (8.2) that can be used to legally override (8.4.8) the abstract method(s) of I.
Let M be the set of abstract methods defined above for I. The descriptor of I consists of the following:
Type parameters, formal parameters, and return types: Let m be a method in M with i) a signature that is a subsignature of every method's signature in M and ii) a return type that is a
subtype of every method's return type in M (after adapting for any type parameters (8.4.4)); if no such method exists, then let m be a method in M that i) has a signature that is a subsignature
of every method's signature in M and ii) is return-type-substitutable for every method in M. Then the descriptor's type parameters, formal parameter types, and return type are as given by m.
Thrown types: The descriptor's thrown types are derived from the throws clauses of the methods in M. If the descriptor is generic, these clauses are first adapted to the type parameters of
the descriptor (8.4.4); if the descriptor is not generic but at least one method in M is, these clauses are first erased. Then the descriptor's thrown types include every type, E, satisfying the
following constraints:
E is mentioned in one of the throws clauses.
For each throws clause, E is a subtype of some type named in that clause.
A functional interface type is one of the following:
A functional interface
A parameterization (4.5) of a functional interface
An intersection (4.9) of interface types that meets the following criteria:
Exactly one element of the intersection is a functional interface, or a parameterization of a functional interface. Let F be this interface.
A notional interface, I, that extends all the interfaces in the intersection would be a functional interface. If any of the intersection elements is a parameterized type, then I is generic: for
each element of the intersection that is a parameterized type J<A1...An>, let P1...Pn be the type parameters of J; then P1...Pn are also type parameters of I, and I extends the type
J<P1...Pn>.
The function descriptor of I is the same as the function descriptor of F.
The function descriptor of a parameterized functional interface, F<A1...An>, where A1...An are type arguments (4.5.1), is derived as follows. Let P1...Pn be the type parameters of F; types
T1...Tn are derived from the type arguments according to the following rules (for 1 ≤ i ≤ n):
If Ai is a type, then Ti = Ai.
If Ai is a upper-bounded wildcard ? extends Ui, then Ti = Ui.
If Ai is a lower-bounded wildcard ? super Li, then Ti = Li.
If Ai is an unbound wildcard ?, then if Pi has upper bound Bi that mentions none of P1...Pn, then Ti = Bi; otherwise, Ti = Object.
If F<T1...Tn> is a well-formed type, then the descriptor of F<A1...An> is the result of applying substitution [P1:=T1, ..., Pn:=Tn] to the descriptor of interface F. Otherwise, the descriptor of
F<A1...An> is undefined.
The function descriptor of an intersection that is a functional interface type is the same as the function descriptor of the functional interface or parameterization of a functional interface that is
an element of the intersection.
59
関数型インターフェース(JLS9.8)
A functional interface is an interface that has just one abstract method, and thus represents a single function contract. (In some cases, this "single" method may take the form of multiple
abstract methods with override-equivalent signatures (8.4.2) inherited from superinterfaces; in this case, the inherited methods logically represent a single method.)
More precisely, for interface I, let M be the set of abstract methods that are members of I but that do not have the same signature as any public instance method of the class Object. Then I is
a functional interface if there exists a method m in M for which the following conditions hold:
The signature of m is a subsignature (8.4.2) of every method's signature in M.
m is return-type-substitutable (8.4.5) for every method in M.
In addition to the usual process of creating an interface instance by declaring (8.1) and instantiating (15.9) a class, instances of functional interfaces can be created with lambda expressions
(15.27), method references (15.28), or constructor references.
The function descriptor of a functional interface I is a method type (8.2) that can be used to legally override (8.4.8) the abstract method(s) of I.
Let M be the set of abstract methods defined above for I. The descriptor of I consists of the following:
Type parameters, formal parameters, and return types: Let m be a method in M with i) a signature that is a subsignature of every method's signature in M and ii) a return type that is a
subtype of every method's return type in M (after adapting for any type parameters (8.4.4)); if no such method exists, then let m be a method in M that i) has a signature that is a subsignature
of every method's signature in M and ii) is return-type-substitutable for every method in M. Then the descriptor's type parameters, formal parameter types, and return type are as given by m.
Thrown types: The descriptor's thrown types are derived from the throws clauses of the methods in M. If the descriptor is generic, these clauses are first adapted to the type parameters of
the descriptor (8.4.4); if the descriptor is not generic but at least one method in M is, these clauses are first erased. Then the descriptor's thrown types include every type, E, satisfying the
following constraints:
E is mentioned in one of the throws clauses.
For each throws clause, E is a subtype of some type named in that clause.
A functional interface type is one of the following:
A functional interface
A parameterization (4.5) of a functional interface
An intersection (4.9) of interface types that meets the following criteria:
Exactly one element of the intersection is a functional interface, or a parameterization of a functional interface. Let F be this interface.
A notional interface, I, that extends all the interfaces in the intersection would be a functional interface. If any of the intersection elements is a parameterized type, then I is generic: for
each element of the intersection that is a parameterized type J<A1...An>, let P1...Pn be the type parameters of J; then P1...Pn are also type parameters of I, and I extends the type
J<P1...Pn>.
The function descriptor of I is the same as the function descriptor of F.
The function descriptor of a parameterized functional interface, F<A1...An>, where A1...An are type arguments (4.5.1), is derived as follows. Let P1...Pn be the type parameters of F; types
T1...Tn are derived from the type arguments according to the following rules (for 1 ≤ i ≤ n):
If Ai is a type, then Ti = Ai.
If Ai is a upper-bounded wildcard ? extends Ui, then Ti = Ui.
If Ai is a lower-bounded wildcard ? super Li, then Ti = Li.
If Ai is an unbound wildcard ?, then if Pi has upper bound Bi that mentions none of P1...Pn, then Ti = Bi; otherwise, Ti = Object.
If F<T1...Tn> is a well-formed type, then the descriptor of F<A1...An> is the result of applying substitution [P1:=T1, ..., Pn:=Tn] to the descriptor of interface F. Otherwise, the descriptor of
F<A1...An> is undefined.
The function descriptor of an intersection that is a functional interface type is the same as the function descriptor of the functional interface or parameterization of a functional interface that is
an element of the intersection.
@
FunctionalInterface
60
@FunctionalInterface
● 関数型インターフェースかどうか検査する
– コンパイル時
@FunctionalInterface
interface F {
boolean equals(Object o);
}
61
@FunctionalInterface
● 関数型インターフェースかどうか検査する
– コンパイル時
@FunctionalInterface
interface F {
boolean equals(Object o);
} @FunctionalInterface
^
Fは機能インタフェースではありません
インタフェース Fで抽象メソッドが見つかりません
エラー1個
62
java.util.function.*
名前 第一引数 第二引数 戻り値
Consumer<T> T - void
Function<T, R> T - R
Predicate<T> T - boolean
Supplier<T> - - T
BiConsumer<T, U> T U void
BiFunction<T, U, R> T U R
BiPredicate<T, R> T U boolean
63
匿名クラスからラムダ式へ
strings.forEach(
new Consumer<String>() {
public void apply(String s) {
System.out.println(s);
}
});
64
匿名クラスからラムダ式へ
strings.forEach(
new Consumer<String>() {
public void apply(String s) {
System.out.println(s);
}
});
forEachの引数から推
論できる
65
匿名クラスからラムダ式へ
strings.forEach(
new Consumer<String>() {
public void apply(String s) {
System.out.println(s);
}
});
実装するべきメソッド
も一意に定まる
66
ラムダ式
strings.forEach(
(String s) -> {
System.out.println(s);
});
● (仮引数) -> {メソッド本体}
● (int n1, int n2) -> {return n1+n2;}
67
ラムダ式
● 関数型インターフェースをインスタンス化
● (仮引数) -> {メソッド本体}
– 型推論で型が決まる
● 関数型インターフェースのインスタンスが
予期される場面で利用可
– ターゲット型
68
ターゲット型が曖昧な場合
Object o = () -> {};
● () -> {}の型として
– Objectが予期される
– 関数型インターフェースが予期されない
– 何を実装したらいいのかわからない
69
ターゲット型が曖昧な場合
Object o = (Runnable)() -> {};
– キャストを用いる
– Runnableが予期される
– 実装するべきインターフェースが分かる
70
ラムダ式の引数
strings.forEach(
(String s) -> {
System.out.println(s);
});
71
ラムダ式の引数
strings.forEach(
(String s) -> {
System.out.println(s);
});
引数の型も一意に定ま
る
72
ラムダ式の引数
strings.forEach(
(s) -> {
System.out.println(s);
});
● 引数の型も省略可
● (n1, n2) -> {return n1+n2;}
73
ラムダ式の引数
strings.forEach(
(s) -> {
System.out.println(s);
});
引数が一つで型が推論される
場合の()は不要
74
ラムダ式の引数
strings.forEach(
s -> {
System.out.println(s);
});
● 引数が一つで型が省略される場合()不要
● n1 -> {return n1+5;}
75
ラムダ式の引数と_
● ラムダ式の引数としての_はコンパイルエラー
this.addActionListener( _ -> {/**/} );
– 他の言語での_は特殊な意味
– 混乱を招かないように利用不可に
– 将来の利用を見据え予約語に
● それ以外の_は警告に
76
ラムダ式のメソッド本体
(int n) -> {return n + 5;}
(n) -> {return n + 5;}
n -> {return n + 5;}
77
ラムダ式のメソッド本体
(int n) -> {return n + 5;}
(n) -> {return n + 5;}
n -> {return n + 5;}
● return文のみ場合,return等を省略できる
(int n) -> n + 5
(n) -> n + 5
n -> n + 5
78
ラムダ式のメソッド本体
(String s) -> {println(s);}
(s) -> {println(s);}
s -> {println(s);}
79
ラムダ式のメソッド本体
(String s) -> {println(s);}
(s) -> {println(s);}
s -> {println(s);}
● 戻り値がvoidでも,{;}を省略できる場合がある
(String s) -> println(s)
(s) -> println(s);
s -> println(s);
80
ラムダ式.equals(匿名クラス)?
81
ラムダ式.equals(匿名クラス)?
● 違います!
– 匿名クラスのシンタックスシュガーではない
● 意味論も実装方法(OpenJDKの場合)も異なる
– 主にスコーピング規則
– 同じ部分もある
82
ラムダ式のスコーピング規則
1.ラムダ式内では外のスコープを引き継ぐ
2.常にアウタークラスのインスタンスを保持しない
– 匿名クラスなどとは大きく違う
3.ローカル変数の参照はfinalな変数のみ
– 匿名クラスと同様
– 注:実質的にfinal(後ほど説明)
83
1.外のスコープを引き継ぐ
class Main {
void method() {
Runnable r = () ->
System.out.println(this);
}
}
84
1.外のスコープを引き継ぐ
class Main {
void method() {
Runnable r = () ->
System.out.println(this);
}
}
● ラムダ式内のthis=エンクロージングクラス
85
1.外のスコープを引き継ぐ
class Main {
void method(int n) {
Runnable r = () -> {int n;};
}
}
86
1.外のスコープを引き継ぐ
class Main {
void method(int n) {
Runnable r = () -> {int n;};
}
}
● 多重定義
● コンパイルエラー
87
1.外のスコープを引き継ぐ
class Main {
void method(int n) {
Function<Integer, Integer> f =
n -> n + 5;
}
}
● 多重定義
● コンパイルエラー
88
2.アウタークラスへの参照
● 匿名クラス
– 常に保持
– メモリリークの危険性高
● ラムダ式
– 必要に応じて保持
89
2.アウタークラスへの参照
class Register {
void register(Processer p) {
p.add(new Func() {
public int f(int n) {return n * n;}
});
}
}
90
2.アウタークラスへの参照
class Register {
void register(Processer p) {
p.add(new Func() {
public int f(int n) {return n * n;}
});
}
}
Registerのインスタンスへの参照が残るRegisterのインスタンスへの参照が残る
91
2.アウタークラスへの参照
class Register {
void register(Processer p) {
p.add(n -> n * n);
}
}
92
2.アウタークラスへの参照
class Register {
void register(Processer p) {
p.add(n -> n * n);
}
}
Registerのインスタンスは保持しない
93
3.ローカル変数の参照
● 匿名クラスと同様
– finalな変数
– 実質的にfinalな変数
● Java8から
● 実質的にfinal
– 再代入されていない変数
– コンパイラがfinal性を推論
– final修飾されている変数と同じ扱い
– 値の変更不可
94
ラムダ式の利用例
p -> p.getName()
s -> Integer.parseInt(s)
(k, v) -> map.put(k, v)
init -> new MyClass(init)
n -> new int[n]
● 引数を受け流すパターン
95
ラムダ式の利用例
p -> p.getName()
s -> Integer.parseInt(s)
(k, v) -> map.put(k, v)
init -> new MyClass(init)
n -> new int[n]
● 引数を受け流すパターン
● メソッド・コンストラクタ参照
96
メソッド・コンストラクタ参照
p -> p.getName()
s -> Integer.parseInt(s)
(k, v) -> map.put(k, v)
init -> new MyClass(init)
n -> new int[n]
● クラス名等::メソッド or new
Person::getName
Integer::perseInt
map::put
MyClass::new
int[]::new
97
ラムダ式との違い
● finalでない変数をレシーバにできる
String s;
while ((s = br.readLine()) != null) {
task.add(() -> s.length()); // NG
task.add(s::length); // OK
}
● 注:この処理はJava8では別の書き方をします
問題点
● 内部イテレーションのほうが長い
– 特に縦に長い
– ラムダ式・メソッド参照で解決
● インターフェースの拡張性が低い
– インターフェースへのメソッド追加
– 追加されたメソッドの実装を追加しないといけない
– デフォルトメソッドで解決
99
<interface>
PublishedInterface
+already()
+exist()
+methods()
100
<interface>
PublishedInterface
+already()
+exist()
+methods()
ReferenceImpl
+already()
+exist()
+methods()
AnotherImpl
+already()
+exist()
+methods()
UserImpl
+already()
+exist()
+methods()
101
<interface>
PublishedInterface
+already()
+exist()
+methods()
+newMethod()
ReferenceImpl
+already()
+exist()
+methods()
AnotherImpl
+already()
+exist()
+methods()
UserImpl
+already()
+exist()
+methods()
102
<interface>
PublishedInterface
+already()
+exist()
+methods()
+newMethod()
ReferenceImpl
+already()
+exist()
+methods()
AnotherImpl
+already()
+exist()
+methods()
UserImpl
+already()
+exist()
+methods()
103
インターフェースに拡張性を
● 新しいメソッドを加えても互換性を保つ
● デフォルトメソッド
– デフォルトの実装を提供する
– インターフェースに実装
– 実装が提供されない場合に使用される
104
デフォルトメソッド
interface Person {
Sex getSex();
default boolean isMan() {
return getSex() == Sex.MAN;
}
}
105
デフォルトメソッド
class PersonImpl implements Person {
public Sex getSex() {/*...*/}
// isManへの実装はなくてもOK
// Person#isManが使われる
}
106
デフォルトメソッド
class PersonImpl implements Person {
public Sex getSex() {/*...*/}
public boolean isMan() {/*...*/}
}
● オーバーライド可
107
デフォルトメソッド
● default修飾子
● publicメソッドとなる
– 既存のインターフェースメソッドと同様
● strictfp修飾のみ可
● 具象クラスで実装が提供されなくても無問題
● 拡張性を実現できた
– 新たな問題が・・・
108
実装の多重継承問題
109
多重継承
class BasicPerson {
public boolean isMan() {/*...*/}
}
class ComplexPerson extends BasicPerson
implements Person {
public Sex getSex() {/*...*/}
}
110
多重継承
BasicPerson
#isMan
Person
#isMan
ComplexPerson
#isMan
111
“Class always win”
112
クラスで定義された実装が
常に勝つ
113
Class always win
class BasicPerson {
public boolean isMan() {/*...*/}
}
class ComplexPerson extends BasicPerson implements
Person {
public Sex getSex() {/*...*/}
}
● BasicPerson#isManが使われる
– “Class always win”
114
親インターフェースの呼び出し
class ComplexPerson extends BasicPerson
implements Person {
public Sex getSex() {/*...*/}
public boolean isMan() {
return Person.super.isMan();
}
}
● インターフェース名.super.メソッド名(...)
115
クラスを介さない多重継承
interface Base1 {default void m() {}}
116
クラスを介さない多重継承
interface Base1 {default void m() {}}
interface Base2 {default void m() {}}
117
クラスを介さない多重継承
interface Base1 {default void m() {}}
interface Base2 {default void m() {}}
interface ExBase extends Base1, Base2 {}
118
多重継承
Base1#m Base2#m
ExBase#m
119
クラスを介さない多重継承
interface ExBase extends
Base1, Base2 {}
● コンパイルエラー
– オーバーライドして選択
120
クラスを介さない多重継承
interface ExBase extends
Base1, Base2 {
default void m() {
Base1.super.m();
}
}
121
多重継承は怖くない!!
● 大原則1:Class always win
– クラスで定義された実装が常に勝つ
● 大原則2:いつでもオーバーライドできる
– 親クラスでfinal修飾されてたら別
– インターフェースの実装を呼べる
122
Objectメソッドのデフォルトメソッド
● Objectで定義されたpublicメソッド
– そもそもデフォルトの実装
● Objectのpublicメソッドのデフォルトメソッドは不可
– interface I {default String toString() {/* */}}
– コンパイルエラー
123
コアライブラリ
Project Lambdaに関連
defaultメソッド
Collections
Framework
StreamAPIOptional
IO/NIO
Concurrensy
Utilities
Logging
Etc...
java.utill.function
Collection拡張の問題点
● データ列はCollectionだけではない
– ファイルの各行もデータ列
– 0から10までの数値もデータ列
● パイプライン化が難しい
– 処理量の増加
Collection拡張の問題点
● データ列はCollectionだけではない
– ファイルの各行もデータ列
– 0から10までの数値もデータ列
● パイプライン化が難しい
– 処理量の増加
処理量の増加
● removeIfしてforEachを考える
strings.removeIf(s -> s.length() > 10);
strings.forEach(System.out::println);
● 2回ループ
処理量の増加
for (Iterator<String> i = strings.iterator();
i.hasNext(); )
if (i.next().length > 10)
i.remove();
for (String s : strings)
System.out.println(s);
StreamAPI
StreamAPI
● 内部イテレーション&パイプライン化
– 処理量そのままに並列化容易
● 汎用性高い
– あらゆる形式のデータ列に対応可
● Collection
● 値の範囲
● 任意の値
など
– データ列自体は保持していない
● データへのアクセス手段を保持
130
StreamAPI
java.util.stream.
● Stream
● IntStream
● LongStream
● DoubleStream
– ソースから生成される
– 中間操作と終端操作でデータを弄る
– 並列化が容易
131
Collection
配列
BufferReader
etc...
Stream
IntStream
LongStream
DoubleStream
中間操作
終端操作
j.u.stream.*Source
132
Collection
配列
BufferReader
etc...
Stream
IntStream
LongStream
DoubleStream
中間操作
終端操作
j.u.stream.*Source
133
Make Streams
ソース メソッド 使用例
Collection Collection#stream list.stream()
配列 Arrays#stream Arrays.stream(args)
BufferedReader BufferedReader#lines br.lines()
n〜m-1までの数値 IntStream#range IntStream.range(n, m)
n〜mまでの数値 IntStream#rangeClosed IntStream.rangeClosed(n, m)
任意の要素 Stream#of Stream.of(“J”, “a”, “v”, “a”)
134
Collection
配列
BufferReader
etc...
Stream
IntStream
LongStream
DoubleStream
中間操作
終端操作
j.u.stream.*Source
135
java.util.stream.
StreamAPI 要素の型
Stream<T> T(参照型)
IntStream int(プリミティブ型)
LongStream long(プリミティブ型)
DoubleStream double(プリミティブ型)
136
2 types of Stream
Sequential Stream
Parallel Stream
137
Change the type of Stream
Sequential Stream
Parallel Stream
parallel() sequential()
138
Collection
配列
BufferReader
etc...
Stream
IntStream
LongStream
DoubleStream
中間操作
終端操作
j.u.stream.*Source
139
中間操作?
● filterやmapなど
– Streamを返すメソッド
● 終端操作が行われるまで処理されない
– 遅延される
140
主要な中間操作
メソッド名 概要 使用例
filter フィルタリング s.filter(n -> n % 2 == 0)
map 写像・変換 s.map(p -> p.getName())
flatMap 写像・変換&平坦化 s.flatMap(room -> room.getPersons().stream())
distinct 同一の要素を除外 s.distinct()
sorted 並び替え s.sorted((p1, p2) -> compare(p1.age, p2.age))
peek
デバッグ向け
forEach
s.peek(e -> System.out.println(e))
limit 要素数制限 s.limit(5)
skip 読み飛ばす s.skip(5)
141
Collection
配列
BufferReader
etc...
Stream
IntStream
LongStream
DoubleStream
非終端操作
終端操作
j.u.stream.*Source
142
終端操作?
● forEachやreduceやcollectなど
– Streamを返さないメソッド
● 遅延されていた中間操作を確定
– 1回のループで済む
143
主要な終端操作
メソッド名 概要 使用例
forEach 反復処理 s.forEach(e -> System.out.println(e))
reduce 畳み込み演算 s.reduce(1, (n1, n2) -> n1 * n2)
collect 集約化 s.collect(Collectors.toList())
toArray 配列化 s.toArray(String[]::new)
min/max 最小値/最大値 s.min(String::compareToIgnoreCase)
count 要素数 s.count()
144
● 0から10まで出力
● 0から10までの偶数を出力
● Personのリストから名前を出力
● 1から100までの総和を出力
● 年齢の合計,平均,最小,最大
● 名前の連結
● Personの名前のリストを得る
● 部署別の社員のリストを得る
145
● 0から10まで出力
● 0から10までの偶数を出力
● Personのリストから名前を出力
● 1から100までの総和を出力
● 年齢の合計,平均,最小,最大
● 名前の連結
● Personの名前のリストを得る
● 部署別の社員のリストを得る
146
0から10まで出力したい
for (int i = 0; i <= 10; i++) {
System.out.println(i);
}
147
forEach[終端]
T->void[j.u.function.Consumer<T>#void accept(T)]
● forEach(T -> void)
– 各要素に引数で渡した処理を行なう
– s.forEach(t -> System.out.println(t));
Stream<T>
IntStream
LongStream
DoubleStream
148
0から10まで出力したい
for (int i = 0; i <= 10; i++) {
System.out.println(i);
}
IntStream.rangeClose(0, 10)
.forEach(i -> System.out.println(i));
149
0から10まで出力したい
for (int i = 0; i <= 10; i++) {
System.out.println(i);
}
IntStream.rangeClose(0, 10)
.forEach(System.out::println);
150
● 0から10まで出力
● 0から10までの偶数を出力
● Personのリストから名前を出力
● 1から100までの総和を出力
● 年齢の合計,平均,最小,最大
● 名前の連結
● Personの名前のリストを得る
● 部署別の社員のリストを得る
151
0から10までの偶数を出力したい
for (int i = 0; i <= 10; i++) {
if (i % 2 == 0) {
System.out.println(i);
}
}
152
filter[中間]
● filter(T -> boolean)
– フィルタリング
– 各要素を引数に適用しtrueを返したもののみ残す
– s.filter(Objects::nonNull) // nullを除外
Stream<T>
IntStream
LongStream
DoubleStream
153
filter[中間]
T->boolean[j.u.function.Predicate<T>#boolean test(T)]
154
0から10までの偶数を出力したい
IntStream.rangeClose(0, 10)
.filter(i -> i % 2 == 0)
.forEach(System.out::println);
155
● 0から10まで出力
● 0から10までの偶数を出力
● Personのリストから名前を出力
● 1から100までの総和を出力
● 年齢の合計,平均,最小,最大
● 名前の連結
● Personの名前のリストを得る
● 部署別の社員のリストを得る
156
Personのリストから名前を出力
for (Person p : persons) {
System.out.println(p.getName());
}
157
Personのリストから名前を出力
for (Person p : persons) {
System.out.println(p.getName());
}
158
map[中間操作]
● map(T -> R)
– 写像・変換
– 各要素を引数に適用した結果のStreamを作る
– personStream.map(p -> p.getName())
– seq.map(n -> n * 2)
Stream<T>
IntStream
LongStream
DoubleStream
159
map[中間操作]
T -> R[java.util.function.Function<T, R>#R map(T)]
R
160
Personのリストから名前を出力
persons.stream()
.map(p -> p.getName())
.forEach(n -> System.out.println(n));
161
Personのリストから名前を出力
persons.stream()
.map(Person::getName)
.forEach(System.out::println);
162
Streamを横断するmap
Stream<T> IntStream
LongStream DoubleStream
#mapToObj
#mapToInt
#mapToLong
#mapToDouble
#mapToDouble
#mapToLong
#mapToInt
163
● 0から10まで出力
● 0から10までの偶数を出力
● Personのリストから名前を出力
● 1から100までの総和を出力
● 年齢の合計,平均,最小,最大
● 名前の連結
● Personの名前のリストを得る
● 部署別の社員のリストを得る
164
1から100までの総和を求める
int sum;
for (int i = 1; i <= 100; i++) {
sum += i;
}
165
reduce[終端]
● Optional<T> reduce((T, T) -> T)
● T reduce(T, (T, T) -> T)
– 集約
– s.reduce((n, m) -> n < m ? n : m)
● Optional
– 値が無いという状態を表すことができる
Stream<T>
IntStream
LongStream
DoubleStream
166
reduce[終端]
167
reduce[終端]
168
reduce[終端]
169
reduce[終端]
170
reduce[終端]
171
reduce[終端]
172
1から100までの総和を求める
int sum = IntStream.rangeClosed(1, 100)
.reduce(0, (l, r) -> l + r);
173
1から100までの総和を求める
int sum = IntStream.rangeClosed(1, 100)
.reduce(0, Integer::sum);
174
1から100までの総和を求める
0 21 2 3 4 5
175
1から100までの総和を求める
1
0 1 2 3 4 5
176
1から100までの総和を求める
1
0 1 2 3 4 5
177
1から100までの総和を求める
1
3
0 1 2 3 4 5
178
1から100までの総和を求める
1
3
0 1 2 3 4 5
179
1から100までの総和を求める
1
3
6
10
16
0 1 2 3 4 5
180
1から100までの総和を求める
int sum = IntStream.rangeClosed(1, 100)
.parallel()
.reduce(0, (l, r) → l + r);
181
1から100までの総和を求める
1 22 3 4 5 6
182
1から100までの総和を求める
1 22 3 4 5 6
183
1から100までの総和を求める
1 22 3 4 5 6
3 7 11
184
1から100までの総和を求める
1 22 3 4 5 6
3 7 11
185
1から100までの総和を求める
6
3 7 11
10
1 22 3 4 5 6
186
1から100までの総和を求める
6
3 7 11
10
1 22 3 4 5 6
187
1から100までの総和を求める
6
3 7 11
10
1 22 3 4 5 6
21
188
sum[終端]
● int sum()
● long sum()
● double sum()
– 総和を求める
● そのものズバリ
– s.sum()
Stream<T>
IntStream
LongStream
DoubleStream
189
1から100までの総和を求める
int sum = IntStream.rangeClosed(1, 100)
.sum();
190
1から100までの総和を求める
int sum = 101 * 100 / 2;
191
● 0から10まで出力
● 0から10までの偶数を出力
● Personのリストから名前を出力
● 1から100までの総和を出力
● 年齢の合計,平均,最小,最大
● 名前の連結
● Personの名前のリストを得る
● 部署別の社員のリストを得る
192
年齢の合計,平均,最大,最小
int sum = 0, max = 0, min = 0;
double ave;
for (Person p : persons) {
int age = p.getAge();
sum += age;
max = Math.max(max, age);
min = Math.min(min, age);
}
ave = sum / (double)persons.size();
193
Ave, max, min[終端]
● average(), max(), min()
– Optional系を返す
– 平均,最大,最小値を求める
Stream<T>
IntStream
LongStream
DoubleStream
194
年齢の合計,平均,最大,最小
int sum = persons.stream()
.mapToInt(Person::getAge).sum();
OptionalInt max = persons.stream()
.mapToInt(Person::getAge).max();
OptionalInt min = persons.stream()
.mapToInt(Person::getAge).min();
OptionalDouble ave = persons.stream()
.mapToInt(Person::getAge).average();
195
年齢の合計,平均,最大,最小
int sum = persons.stream()
.mapToInt(Person::getAge).sum();
OptionalInt max = persons.stream()
.mapToInt(Person::getAge).max();
OptionalInt min = persons.stream()
.mapToInt(Person::getAge).min();
OptionalDouble ave = persons.stream()
.mapToInt(Person::getAge).average();
ループ四回
196
年齢の合計,平均,最大,最小
IntStream s = persons.stream()
.mapToInt(Person::getAge);
int sum = s.sum();
OptionalInt max = s.max();
OptionalInt min = s.min();
OptionalDouble ave = s.average();
197
年齢の合計,平均,最大,最小
IntStream s = persons.stream()
.mapToInt(Person::getAge);
int sum = s.sum();
OptionalInt max = s.max();
OptionalInt min = s).min();
OptionalDouble ave = s.average();
IllegalStateException
198
summaryStatistics[終端]
● XxxSummaryStatistics
summaryStatistics()
– 統計処理
● 合計,平均,最大,最小,個数
– stream.summaryStatistics().getSum()
Stream<T>
IntStream
LongStream
DoubleStream
199
年齢の合計,平均,最大,最小
IntSummaryStatistics iss = persons.stream()
.mapToInt(Person::getAge)
.summaryStatistics();
200
年齢の合計,平均,最大,最小
IntSummaryStatistics iss = persons.stream()
.mapToInt(Person::getAge)
.summaryStatistics();
int sum = iss.getSum();
int min = iss.getMin(), max = iss.getMax();
double ave = iss.getAverage();
int count = iss.getCount();
201
● 0から10まで出力
● 0から10までの偶数を出力
● Personのリストから名前を出力
● 1から100までの総和を出力
● 年齢の合計,平均,最小,最大
● 名前の連結
● Personの名前のリストを得る
● 部署別の社員のリストを得る
202
生徒の名前を連結する
StringBuilder sb = new StringBuilder();
for (Student s : students) {
sb.append(s.getName());
}
String name = sb.toString();
203
生徒の名前を連結する
String name = students.stream()
.map(Student::getName)
.reduce(“”, (l, r) -> l + r);
204
生徒の名前を連結する
String name = students.stream()
.map(Student::getName)
.reduce(“”, (l, r) -> l + r);
Stringの連結
205
生徒の名前を連結する
String name = students.stream()
.map(Student::getName)
.map(StringBuilder::new)
.reduce(new StringBuilder(),
(l, r) -> l.append(r))
.toString();
206
生徒の名前を連結する
String name = students.stream()
.map(Student::getName)
.map(StringBuilder::new)
.reduce(new StringBuilder(),
(l, r) -> l.append(r))
.toString();
StringBuilderの
連結
207
collect
● R collect(() -> R, (R, T) -> R, (R, R) -> void)
● R collect(Collector<T, ?, R>)
– 集約処理
– R:集約先のオブジェクト
– () -> R:集約先のオブジェクトの生成
– (R, T) -> R:集約先のオブジェクトに要素を集約
– (R, R) -> void:集約先のオブジェクト同士のcombine
● 並列処理用
208
生徒の名前を連結する
String name = students.stream()
.map(Student::getName)
.collect(_________________________,
_______________________,
_____________________________)
.toString();
209
生徒の名前を連結する
String name = students.stream()
.map(Student::getName)
.collect(() -> new StringBuilder(),
_______________________,
_____________________________)
.toString();
210
生徒の名前を連結する
String name = students.stream()
.map(Student::getName)
.collect(() -> new StringBuilder(),
(sb, s) -> sb.append(s),
_____________________________)
.toString();
211
生徒の名前を連結する
String name = students.stream()
.map(Student::getName)
.collect(() -> new StringBuilder(),
(sb, s) -> sb.append(s),
(sb1, sb2) -> sb1.append(sb2))
.toString();
212
生徒の名前を連結する
String name = students.stream()
.map(Student::getName)
.collect(StringBuilder::new,
StringBuilder::append,
StringBuilder::append)
.toString();
213
Sequential
collect(SB::new, SB::append, SB::append)
H e l l o , W o r l d !H e l lH e o , W o r l d !
214
H e l l o , W o r l d !
SB
Sequential
collect(SB::new, SB::append, SB::append)
H e l l o , W o r l d !H e l lH e o , W o r l d !
SB
215
H e l l o , W o r l d !
SB
Sequential
collect(SB::new, SB::append, SB::append)
H e l l o , W o r l d !H e l lH e o , W o r l d !
SB
216
H e l l o , W o r l d !
SB
Sequential
collect(SB::new, SB::append, SB::append)
H e l l o , W o r l d !H e l lH e o , W o r l d !
SB
217
Parallel
collect(SB::new, SB::append, SB::append)
H e l l o , W o r l d !H e l l o , W o r l d !H e l lH e o , W o r l d !
218
Parallel
collect(SB::new, SB::append, SB::append)
H e l l o , W o r l d !
Split!!
H e o ,l l W o r l d !
219
Parallel
collect(SB::new, SB::append, SB::append)
H e l l o , W o r l d !H e o ,l l W o r l d !
220
Parallel
collect(SB::new, SB::append, SB::append)
H e l l o , W o r l d !
He WoHe WoWoWoWoHeHe
H e o ,l l W o r l d !
221
Parallel
collect(SB::new, SB::append, SB::append)
H e l l o , W o r l d !
He WoWoWoWoHeHe
H e o ,l l W o r l d !
222
Parallel
collect(SB::new, SB::append, SB::append)
H e l l o , W o r l d !
He WoHe WoWoWoWoHeHe
H e o ,l l W o r l d !
223
Parallel
collect(SB::new, SB::append, SB::append)
H e l l o , W o r l d !
He WoSBll SBd!He WoWoWoWoHeHe
H e o ,l l W o r l d !
SBllHeHeWoll SBd!SBllHeHeWod!
224
Parallel
collect(SB::new, SB::append, SB::append)
H e l l o , W o r l d !
He WoSBll SBd!He WoWoWoWoHeHe
H e o ,l l W o r l d !
HeHeWoll SBllHeHeWod!
225
Parallel
collect(SB::new, SB::append, SB::append)
H e l l o , W o r l d !
Hell Wo SBd!WoWoWo
H e o ,l l W o r l d !
SBd!SBllHeHeWod!Hell
226
Parallel
collect(SB::new, SB::append, SB::append)
H e l l o , W o r l d !
Hell Wo SBd!WoWoWoWo
H e o ,l l W o r l d !
SBd!SBllHeHeWod!Hell
227
Parallel
collect(SB::new, SB::append, SB::append)
H e l l o , W o r l d !
Hell Wo SBd!SBo, SBrlWoWoWoWo
H e o ,l l W o r l d !
Hell SBd!SBd!SBllHeHeWod!Wo SBd!WoWoWoWo SBd!SBd!SBllHeHeWod!SBd!SBd!SBd!SBllHeHeWod!SBd!SBd!SBd!SBllHeHeWorlSBd!SBd!SBd!SBllHeHeWod!SBd!SBd!SBd!SBllHeHeWoo,
228
Parallel
collect(SB::new, SB::append, SB::append)
H e l l o , W o r l d !
Hell Wo SBd!SBo, SBrlWoWoWoWo
H e o ,l l W o r l d !
Hell SBd!SBd!SBllHeHeWod!SBo, SBrlSBd!SBd!SBd!SBllHeHeWod!SBd!SBd!SBd!SBllHeHeWorlSBd!SBd!SBd!SBllHeHeWod!SBd!SBd!SBd!SBllHeHeWoo,
229
Parallel
collect(SB::new, SB::append, SB::append)
H e l l o , W o r l d !
Hello, Worl SBd!
H e o ,l l W o r l d !
SBd!SBd!SBllHeHeWod!
230
Parallel
collect(SB::new, SB::append, SB::append)
H e l l o , W o r l d !
Hello, Worl SBd!
H e o ,l l W o r l d !
SBd!SBd!SBllHeHeWod!
231
Parallel
collect(SB::new, SB::append, SB::append)
H e l l o , W o r l d !
Hello,Worl SBd!
H e o ,l l W o r l d !
SBd!SBd!SBllHeHeWod!
232
Parallel
collect(SB::new, SB::append, SB::append)
H e l l o , W o r l d !
Hello,Worl SBd!
H e o ,l l W o r l d !
SBd!SBd!SBllHeHeWod!
233
Parallel
collect(SB::new, SB::append, SB::append)
H e l l o , W o r l d !
Hello,World!
H e o ,l l W o r l d !
234
Collectors#joining
● Collector<CharSeq, ?, String>
joining()
joining(delimiter)
joining(delimiter, prefix, suffix)
– 文字列の連結をするCollectorを返す
– 単なる連結だけでなく,デリミタなども指定可
235
生徒の名前を連結する
String name = students.stream()
.map(Student::getName)
.collect(Collectors.joining());
AliceBobCharlie
236
生徒の名前を連結する
String name = students.stream()
.map(Student::getName)
.collect(Collectors.joining(“, ”));
Alice, Bob, Charlie
237
生徒の名前を連結する
String name = students.stream()
.map(Student::getName)
.collect(Collectors
.joining(“, ”, “[”, “]”));
[Alice, Bob, Charlie]
238
● 0から10まで出力
● 0から10までの偶数を出力
● Personのリストから名前を出力
● 1から100までの総和を出力
● 年齢の合計,平均,最小,最大
● 名前の連結
● Personの名前のリストを得る
● 部署別の社員のリストを得る
239
Personのリストから名前のリスト
List<String> names = new ArrayList<>();
for (Person p : persons) {
names.add(p.getName());
}
240
Collectors#toXxx
● toCollection()
● toList()
● toSet()
– リストなどへの集約をするCollector
241
Personのリストから名前のリスト
persons.stream()
.map(Person::getName)
.collect(Collectors.toList())
242
● 0から10まで出力
● 0から10までの偶数を出力
● Personのリストから名前を出力
● 1から100までの総和を出力
● 年齢の合計,平均,最小,最大
● 名前の連結
● Personの名前のリストを得る
● 部署別の社員のリストを得る
243
社員の部署別のMapを得たい
Map<Dep, List<Emp>> empsByDep =
new HashMap<>();
for (Emp e : emps) {
Dep d = e.getDep();
if (empsByDep.containsKey(d)) {
empsByDep.put(d, new ArrayList<>());
}
empsByDep.get(d).add(e);
}
244
社員の部署別のMapを得たい
Map<Dep, List<Emp>> empsByDep =
new HashMap<>();
for (Emp e : emps) {
Dep d = e.getDep();
empsByDep.computeIfAbsent(d,
ArrayList::new)
.add(e);
}
245
Collectors#groupingBy
● Collector<T, ?, Map<K, List<T>>
groupingBy(T -> K)
groupingByConcurrent(T -> K)
– 型Kでグループ化
246
社員の部署別のMapを得たい
Map<Dep, List<Emp>> empsByDep =
emps.stream()
.collect(Collectors.groupingBy(
Emp::getDep));
247
Streamと並列処理
248
Streamと並列処理
● parallel()で並列モードへ
– 適度な大きさで分割してFork/Join
● すべての場合で並列化できるのか?
– No
– Streamが様々な情報を考慮して並列化する
● データ数
● 終端操作の内容
– 処理の順序に依存する物は並列化しにくい
249
Streamと並列処理
● 並列化したら早くなるのか
– 一概には言えない・・・
● データ数依存
● マシン依存
● 操作依存
– 早くなるものもある
– 並列化に際してはベンチマーク必須
250
並列処理で早くならないんだったら
今までのfor文でいいやー
251
並列処理で早くならないんだったら
今までのfor文でいいやー
● やめましょう!
– 簡単なイテレーションはStreamで
– 複雑なイテレーションを要するものはfor文で
● Streamを使った時のメリット
– 並列処理化に簡単に対応できる
● .parallel()を挟むだけ
– 将来実装が変わって,何もしなくても早くなるかも
● JDK開発者が頑張る
252
Project Lambdaまとめ
● もともとはマルチコア対応
● 結果としては汎用的な仕様に
– ラムダ式等
– コアライブラリ
● よりスマートなコードへ
– RubyやScalaっぽい
253
Thank you for your listening
Enjoy JavaSE8

More Related Content

What's hot

【java8 勉強会】 怖くない!ラムダ式, Stream API
【java8 勉強会】 怖くない!ラムダ式, Stream API【java8 勉強会】 怖くない!ラムダ式, Stream API
【java8 勉強会】 怖くない!ラムダ式, Stream APIdcomsolution
 
磯野ー!関数型言語やろうぜー!
磯野ー!関数型言語やろうぜー!磯野ー!関数型言語やろうぜー!
磯野ー!関数型言語やろうぜー!Ra Zon
 
Java x Groovy: improve your java development life
Java x Groovy: improve your java development lifeJava x Groovy: improve your java development life
Java x Groovy: improve your java development lifeUehara Junji
 
Python と型アノテーション
Python と型アノテーションPython と型アノテーション
Python と型アノテーションK Yamaguchi
 
「再代入なんて、あるわけない」 ~ふつうのプログラマが関数型言語を知るべき理由~ (Gunma.web #5 2011/05/14)
「再代入なんて、あるわけない」 ~ふつうのプログラマが関数型言語を知るべき理由~ (Gunma.web #5 2011/05/14)「再代入なんて、あるわけない」 ~ふつうのプログラマが関数型言語を知るべき理由~ (Gunma.web #5 2011/05/14)
「再代入なんて、あるわけない」 ~ふつうのプログラマが関数型言語を知るべき理由~ (Gunma.web #5 2011/05/14)parrotstudio
 
ステップ・バイ・ステップで学ぶラムダ式・Stream api入門 #jjug ccc #ccc h2
ステップ・バイ・ステップで学ぶラムダ式・Stream api入門 #jjug ccc #ccc h2ステップ・バイ・ステップで学ぶラムダ式・Stream api入門 #jjug ccc #ccc h2
ステップ・バイ・ステップで学ぶラムダ式・Stream api入門 #jjug ccc #ccc h2Masatoshi Tada
 
Java SE 8 lambdaで変わる プログラミングスタイル
Java SE 8 lambdaで変わる プログラミングスタイルJava SE 8 lambdaで変わる プログラミングスタイル
Java SE 8 lambdaで変わる プログラミングスタイルなおき きしだ
 
from old Java to modern Java
from old Java to modern Javafrom old Java to modern Java
from old Java to modern Java心 谷本
 
Pythonと型チェッカー
Pythonと型チェッカーPythonと型チェッカー
Pythonと型チェッカーTetsuya Morimoto
 
Shibuya.lisp #28: 仮題: R について
Shibuya.lisp #28: 仮題: R についてShibuya.lisp #28: 仮題: R について
Shibuya.lisp #28: 仮題: R についてtnoda
 
The Why and How of Java8 at LINE Fukuoka
The Why and How of Java8 at LINE FukuokaThe Why and How of Java8 at LINE Fukuoka
The Why and How of Java8 at LINE FukuokaYouhei Nitta
 
Java8のstreamをダラダラまとめてみる
Java8のstreamをダラダラまとめてみるJava8のstreamをダラダラまとめてみる
Java8のstreamをダラダラまとめてみるShinya Mochida
 
JDK 10 へようこそ
JDK 10 へようこそJDK 10 へようこそ
JDK 10 へようこそDavid Buck
 
静的型付け言語Python
静的型付け言語Python静的型付け言語Python
静的型付け言語Pythonkiki utagawa
 
Javaセキュアコーディングセミナー東京第3回講義
Javaセキュアコーディングセミナー東京第3回講義Javaセキュアコーディングセミナー東京第3回講義
Javaセキュアコーディングセミナー東京第3回講義JPCERT Coordination Center
 
Shibuya JVM Groovy 20150418
Shibuya JVM Groovy 20150418Shibuya JVM Groovy 20150418
Shibuya JVM Groovy 20150418Uehara Junji
 
Functional Programming in Swift
Functional Programming in SwiftFunctional Programming in Swift
Functional Programming in SwiftKaz Yoshikawa
 
Cookpad Summer Intern 2015 - Programming Paradigm
Cookpad Summer Intern 2015 - Programming ParadigmCookpad Summer Intern 2015 - Programming Paradigm
Cookpad Summer Intern 2015 - Programming ParadigmMinero Aoki
 

What's hot (20)

【java8 勉強会】 怖くない!ラムダ式, Stream API
【java8 勉強会】 怖くない!ラムダ式, Stream API【java8 勉強会】 怖くない!ラムダ式, Stream API
【java8 勉強会】 怖くない!ラムダ式, Stream API
 
磯野ー!関数型言語やろうぜー!
磯野ー!関数型言語やろうぜー!磯野ー!関数型言語やろうぜー!
磯野ー!関数型言語やろうぜー!
 
Java x Groovy: improve your java development life
Java x Groovy: improve your java development lifeJava x Groovy: improve your java development life
Java x Groovy: improve your java development life
 
Python と型アノテーション
Python と型アノテーションPython と型アノテーション
Python と型アノテーション
 
「再代入なんて、あるわけない」 ~ふつうのプログラマが関数型言語を知るべき理由~ (Gunma.web #5 2011/05/14)
「再代入なんて、あるわけない」 ~ふつうのプログラマが関数型言語を知るべき理由~ (Gunma.web #5 2011/05/14)「再代入なんて、あるわけない」 ~ふつうのプログラマが関数型言語を知るべき理由~ (Gunma.web #5 2011/05/14)
「再代入なんて、あるわけない」 ~ふつうのプログラマが関数型言語を知るべき理由~ (Gunma.web #5 2011/05/14)
 
ステップ・バイ・ステップで学ぶラムダ式・Stream api入門 #jjug ccc #ccc h2
ステップ・バイ・ステップで学ぶラムダ式・Stream api入門 #jjug ccc #ccc h2ステップ・バイ・ステップで学ぶラムダ式・Stream api入門 #jjug ccc #ccc h2
ステップ・バイ・ステップで学ぶラムダ式・Stream api入門 #jjug ccc #ccc h2
 
Java8勉強会
Java8勉強会Java8勉強会
Java8勉強会
 
Java SE 8 lambdaで変わる プログラミングスタイル
Java SE 8 lambdaで変わる プログラミングスタイルJava SE 8 lambdaで変わる プログラミングスタイル
Java SE 8 lambdaで変わる プログラミングスタイル
 
from old Java to modern Java
from old Java to modern Javafrom old Java to modern Java
from old Java to modern Java
 
Pythonと型チェッカー
Pythonと型チェッカーPythonと型チェッカー
Pythonと型チェッカー
 
Shibuya.lisp #28: 仮題: R について
Shibuya.lisp #28: 仮題: R についてShibuya.lisp #28: 仮題: R について
Shibuya.lisp #28: 仮題: R について
 
The Why and How of Java8 at LINE Fukuoka
The Why and How of Java8 at LINE FukuokaThe Why and How of Java8 at LINE Fukuoka
The Why and How of Java8 at LINE Fukuoka
 
Java8のstreamをダラダラまとめてみる
Java8のstreamをダラダラまとめてみるJava8のstreamをダラダラまとめてみる
Java8のstreamをダラダラまとめてみる
 
JDK 10 へようこそ
JDK 10 へようこそJDK 10 へようこそ
JDK 10 へようこそ
 
静的型付け言語Python
静的型付け言語Python静的型付け言語Python
静的型付け言語Python
 
Javaセキュアコーディングセミナー東京第3回講義
Javaセキュアコーディングセミナー東京第3回講義Javaセキュアコーディングセミナー東京第3回講義
Javaセキュアコーディングセミナー東京第3回講義
 
Shibuya JVM Groovy 20150418
Shibuya JVM Groovy 20150418Shibuya JVM Groovy 20150418
Shibuya JVM Groovy 20150418
 
Functional Programming in Swift
Functional Programming in SwiftFunctional Programming in Swift
Functional Programming in Swift
 
APIKit
APIKitAPIKit
APIKit
 
Cookpad Summer Intern 2015 - Programming Paradigm
Cookpad Summer Intern 2015 - Programming ParadigmCookpad Summer Intern 2015 - Programming Paradigm
Cookpad Summer Intern 2015 - Programming Paradigm
 

Similar to Brand new Data Processing - StreamAPI

Chainerの使い方と 自然言語処理への応用
Chainerの使い方と自然言語処理への応用Chainerの使い方と自然言語処理への応用
Chainerの使い方と 自然言語処理への応用Yuya Unno
 
全力解説!Transformer
全力解説!Transformer全力解説!Transformer
全力解説!TransformerArithmer Inc.
 
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第6回 ‟文字列とオブジェクト„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第6回 ‟文字列とオブジェクト„【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第6回 ‟文字列とオブジェクト„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第6回 ‟文字列とオブジェクト„和弘 井之上
 
「深層学習」勉強会LT資料 "Chainer使ってみた"
「深層学習」勉強会LT資料 "Chainer使ってみた"「深層学習」勉強会LT資料 "Chainer使ってみた"
「深層学習」勉強会LT資料 "Chainer使ってみた"Ken'ichi Matsui
 
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第2回 ‟変数と型„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第2回 ‟変数と型„【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第2回 ‟変数と型„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第2回 ‟変数と型„和弘 井之上
 
これからの「言語」の話をしよう ―― 未来を生きるためのツール
これからの「言語」の話をしよう ―― 未来を生きるためのツールこれからの「言語」の話をしよう ―― 未来を生きるためのツール
これからの「言語」の話をしよう ―― 未来を生きるためのツールNobuhisa Koizumi
 
知って得するWebで便利なpostgre sqlの3つの機能
知って得するWebで便利なpostgre sqlの3つの機能知って得するWebで便利なpostgre sqlの3つの機能
知って得するWebで便利なpostgre sqlの3つの機能Soudai Sone
 
[DL輪読会]Control as Inferenceと発展
[DL輪読会]Control as Inferenceと発展[DL輪読会]Control as Inferenceと発展
[DL輪読会]Control as Inferenceと発展Deep Learning JP
 
機械学習モデルフォーマットの話:さようならPMML、こんにちはPFA
機械学習モデルフォーマットの話:さようならPMML、こんにちはPFA機械学習モデルフォーマットの話:さようならPMML、こんにちはPFA
機械学習モデルフォーマットの話:さようならPMML、こんにちはPFAShohei Hido
 
Good Parts of PHP and the UNIX Philosophy
Good Parts of PHP and the UNIX PhilosophyGood Parts of PHP and the UNIX Philosophy
Good Parts of PHP and the UNIX PhilosophyYuya Takeyama
 
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第4回 ‟関数„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第4回 ‟関数„【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第4回 ‟関数„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第4回 ‟関数„和弘 井之上
 
TypeScript & 関数型講座 第3回 関数型入門
TypeScript & 関数型講座 第3回 関数型入門TypeScript & 関数型講座 第3回 関数型入門
TypeScript & 関数型講座 第3回 関数型入門gypsygypsy
 
【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第4回 「Function と Pro...
【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第4回 「Function と Pro...【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第4回 「Function と Pro...
【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第4回 「Function と Pro...Kaz Aiso
 
genuine-highlighter: マクロを認識するClojure向けのシンタックスハイライター
genuine-highlighter: マクロを認識するClojure向けのシンタックスハイライターgenuine-highlighter: マクロを認識するClojure向けのシンタックスハイライター
genuine-highlighter: マクロを認識するClojure向けのシンタックスハイライターsohta
 
Chainer入門と最近の機能
Chainer入門と最近の機能Chainer入門と最近の機能
Chainer入門と最近の機能Yuya Unno
 

Similar to Brand new Data Processing - StreamAPI (20)

Chainerの使い方と 自然言語処理への応用
Chainerの使い方と自然言語処理への応用Chainerの使い方と自然言語処理への応用
Chainerの使い方と 自然言語処理への応用
 
たのしい関数型
たのしい関数型たのしい関数型
たのしい関数型
 
全力解説!Transformer
全力解説!Transformer全力解説!Transformer
全力解説!Transformer
 
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第6回 ‟文字列とオブジェクト„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第6回 ‟文字列とオブジェクト„【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第6回 ‟文字列とオブジェクト„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第6回 ‟文字列とオブジェクト„
 
「深層学習」勉強会LT資料 "Chainer使ってみた"
「深層学習」勉強会LT資料 "Chainer使ってみた"「深層学習」勉強会LT資料 "Chainer使ってみた"
「深層学習」勉強会LT資料 "Chainer使ってみた"
 
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第2回 ‟変数と型„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第2回 ‟変数と型„【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第2回 ‟変数と型„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第2回 ‟変数と型„
 
これからの「言語」の話をしよう ―― 未来を生きるためのツール
これからの「言語」の話をしよう ―― 未来を生きるためのツールこれからの「言語」の話をしよう ―― 未来を生きるためのツール
これからの「言語」の話をしよう ―― 未来を生きるためのツール
 
知って得するWebで便利なpostgre sqlの3つの機能
知って得するWebで便利なpostgre sqlの3つの機能知って得するWebで便利なpostgre sqlの3つの機能
知って得するWebで便利なpostgre sqlの3つの機能
 
Thinking in Cats
Thinking in CatsThinking in Cats
Thinking in Cats
 
Introduction of Python
Introduction of PythonIntroduction of Python
Introduction of Python
 
[DL輪読会]Control as Inferenceと発展
[DL輪読会]Control as Inferenceと発展[DL輪読会]Control as Inferenceと発展
[DL輪読会]Control as Inferenceと発展
 
機械学習モデルフォーマットの話:さようならPMML、こんにちはPFA
機械学習モデルフォーマットの話:さようならPMML、こんにちはPFA機械学習モデルフォーマットの話:さようならPMML、こんにちはPFA
機械学習モデルフォーマットの話:さようならPMML、こんにちはPFA
 
Good Parts of PHP and the UNIX Philosophy
Good Parts of PHP and the UNIX PhilosophyGood Parts of PHP and the UNIX Philosophy
Good Parts of PHP and the UNIX Philosophy
 
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第4回 ‟関数„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第4回 ‟関数„【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第4回 ‟関数„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第4回 ‟関数„
 
ATN No.2 Scala事始め
ATN No.2 Scala事始めATN No.2 Scala事始め
ATN No.2 Scala事始め
 
TypeScript & 関数型講座 第3回 関数型入門
TypeScript & 関数型講座 第3回 関数型入門TypeScript & 関数型講座 第3回 関数型入門
TypeScript & 関数型講座 第3回 関数型入門
 
【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第4回 「Function と Pro...
【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第4回 「Function と Pro...【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第4回 「Function と Pro...
【DELPHI / C++BUILDER STARTER チュートリアルシリーズ】 シーズン2 Delphi の部 第4回 「Function と Pro...
 
Project lambda
Project lambdaProject lambda
Project lambda
 
genuine-highlighter: マクロを認識するClojure向けのシンタックスハイライター
genuine-highlighter: マクロを認識するClojure向けのシンタックスハイライターgenuine-highlighter: マクロを認識するClojure向けのシンタックスハイライター
genuine-highlighter: マクロを認識するClojure向けのシンタックスハイライター
 
Chainer入門と最近の機能
Chainer入門と最近の機能Chainer入門と最近の機能
Chainer入門と最近の機能
 

More from bitter_fox

Introduction to JShell #JavaDayTokyo #jdt_jshell
Introduction to JShell #JavaDayTokyo #jdt_jshellIntroduction to JShell #JavaDayTokyo #jdt_jshell
Introduction to JShell #JavaDayTokyo #jdt_jshellbitter_fox
 
10のJava9で変わるJava8の嫌なとこ!
10のJava9で変わるJava8の嫌なとこ!10のJava9で変わるJava8の嫌なとこ!
10のJava9で変わるJava8の嫌なとこ!bitter_fox
 
Introduction to JShell: the Java REPL Tool #jjug_ccc #ccc_ab4
Introduction to JShell: the Java REPL Tool #jjug_ccc #ccc_ab4Introduction to JShell: the Java REPL Tool #jjug_ccc #ccc_ab4
Introduction to JShell: the Java REPL Tool #jjug_ccc #ccc_ab4bitter_fox
 
JavaOne2014サンフランシスコ報告会in大阪
JavaOne2014サンフランシスコ報告会in大阪JavaOne2014サンフランシスコ報告会in大阪
JavaOne2014サンフランシスコ報告会in大阪bitter_fox
 
RCC LT 2013 Javaを日本語で書けるようにしてみた(言語処理)
RCC LT 2013 Javaを日本語で書けるようにしてみた(言語処理)RCC LT 2013 Javaを日本語で書けるようにしてみた(言語処理)
RCC LT 2013 Javaを日本語で書けるようにしてみた(言語処理)bitter_fox
 
Lt (コピー)
Lt (コピー)Lt (コピー)
Lt (コピー)bitter_fox
 

More from bitter_fox (6)

Introduction to JShell #JavaDayTokyo #jdt_jshell
Introduction to JShell #JavaDayTokyo #jdt_jshellIntroduction to JShell #JavaDayTokyo #jdt_jshell
Introduction to JShell #JavaDayTokyo #jdt_jshell
 
10のJava9で変わるJava8の嫌なとこ!
10のJava9で変わるJava8の嫌なとこ!10のJava9で変わるJava8の嫌なとこ!
10のJava9で変わるJava8の嫌なとこ!
 
Introduction to JShell: the Java REPL Tool #jjug_ccc #ccc_ab4
Introduction to JShell: the Java REPL Tool #jjug_ccc #ccc_ab4Introduction to JShell: the Java REPL Tool #jjug_ccc #ccc_ab4
Introduction to JShell: the Java REPL Tool #jjug_ccc #ccc_ab4
 
JavaOne2014サンフランシスコ報告会in大阪
JavaOne2014サンフランシスコ報告会in大阪JavaOne2014サンフランシスコ報告会in大阪
JavaOne2014サンフランシスコ報告会in大阪
 
RCC LT 2013 Javaを日本語で書けるようにしてみた(言語処理)
RCC LT 2013 Javaを日本語で書けるようにしてみた(言語処理)RCC LT 2013 Javaを日本語で書けるようにしてみた(言語処理)
RCC LT 2013 Javaを日本語で書けるようにしてみた(言語処理)
 
Lt (コピー)
Lt (コピー)Lt (コピー)
Lt (コピー)
 

Recently uploaded

20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directory20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directoryosamut
 
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。iPride Co., Ltd.
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略Ryo Sasaki
 
Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By DanielPostman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Danieldanielhu54
 
PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000Shota Ito
 
UPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdfUPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdffurutsuka
 
IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxIoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxAtomu Hidaka
 
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。
新人研修のまとめ       2024/04/12の勉強会で発表されたものです。新人研修のまとめ       2024/04/12の勉強会で発表されたものです。
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。iPride Co., Ltd.
 
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムsugiuralab
 

Recently uploaded (9)

20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directory20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directory
 
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
 
Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By DanielPostman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Daniel
 
PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000
 
UPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdfUPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdf
 
IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxIoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
 
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。
新人研修のまとめ       2024/04/12の勉強会で発表されたものです。新人研修のまとめ       2024/04/12の勉強会で発表されたものです。
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。
 
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システム
 

Brand new Data Processing - StreamAPI