SlideShare a Scribd company logo
1 of 188
Download to read offline
1
徹
底
解
説
!
Project Lambdaのすべて
2013/11/9 14:15-15:05
JJUG CCC 2013 Fall H-2
@bitter_fox
2
Who are you?
● Twitter: @bitter_fox
● 職業: 学生
– 立命館大学 情報理工学部 情報システム学科
– 二回生
– 立命館コンピュータクラブ
3
Who are you?
● Twitter: @bitter_fox
● Like
– Java
– Xmonad
– Scala
– etc.
4
Who are you?
● Twitter: @bitter_fox
● コミュニティ活動
– カンファレンス系初参加
– しかも初登壇
● めちゃくちゃ緊張してます
5
HashTag @ Twitter
#jjug_ccc
#ccc_h2
6
JavaSE8
7
JavaSE8
Revolution
8
JavaSE8
Project Lambda
Revolution
9
Project Lambda
● 並列処理を容易に書ける様に増強
– ライブラリ
– 言語
● StreamAPI(!=IOStream)の導入
● ラムダ式の導入
10
Why Project Lambda?
11
マルチコアCPU
12
マルチコアCPU
● CPUのパラダイムシフト
– クロック数はそのまま
コア(数)を増やす
– 並列処理
● ソフトウェアにもパラダイムシフト
● 並列プログラミングにしないと性能をフルに利用で
きない
– アムダールの法則
13
アムダールの法則
90% 10%
90%
80% 20%
80%
5
%
1コア
1コア
∞コア
4コア
逐次処理 並列処理
14
現代的なアーキテクチャ
少しでも多くの部分で並列処理
15
プロジェクト発足当時の並列処理
大きな粒度のみ
小さい粒度には向かない
求められているのは小さな粒度
16
マルチコアCPUの
台頭
マルチコアCPUコアライブラリ
17
ライブラリでは不十分
new Runnable(){
public void run(){
// proc
}
}
● 処理を分けるだけで5行
● いくらライブラリが良くても・・・
● 言語的に解決する必要がある
18
マルチコアCPUコアライブラリ
ラムダ式・メソッド参照
19
マルチコアCPUコアライブラリ
ラムダ式・メソッド参照
実質的にfinal
型推論の強化
複合型キャスト
20
ライブラリの増強
● 一度公開されたインターフェース
– 変更を加えにくい
– メソッド追加
● 具象クラスが追随する必要がある
– 実装の提供
21
マルチコアCPUコアライブラリ
ラムダ式・メソッド参照
実質的にfinal
型推論の強化
複合型キャスト
デフォルト実装
22
マルチコアCPUコアライブラリ
ラムダ式・メソッド参照
実質的にfinal
型推論の強化
複合型キャスト
デフォルト実装
stat. intf. メソッド
23
マルチコアCPUコアライブラリ
ラムダ式・メソッド参照
実質的にfinal
型推論の強化
複合型キャスト
デフォルト実装
stat. intf. メソッド
ラムダ式・メソッド参照
24
処理の分離のイディオム
new Runnable() {
public void run() {
//
}
}
25
処理の分離のイディオム
new Runnable() {
public void run() {
//
}
}
実装するべきメソッドが一つ
インターフェース
26
● 実装するべきメソッド(抽象メソッド)が一つ
● インターフェース
– java.lang.Runnable
– java.lang.Callable
– java.nio.file.PathMatcher
– java.awt.event.ActionListener
– java.swing.event.ChangeListner
– ...
27
関数型インターフェース
● 実装するべきメソッド(抽象メソッド)が一つ
● インターフェース
– java.lang.Runnable
– java.lang.Callable
– java.nio.file.PathMatcher
– java.awt.event.ActionListener
– java.swing.event.ChangeListner
– ...
28
関数型インターフェース
● 処理を分けるのに十分
● ライブラリの多くで利用されている
● 実装&インスタンス化する構文としてラムダ式
29
関数型インターフェース?
interface F {
void f();
}
30
関数型インターフェース?
interface F {
void f();
}
● Yes!
31
関数型インターフェース?
interface F {
boolean equals(Object o);
}
32
関数型インターフェース?
interface F {
boolean equals(Object o);
}
● No!
● equalsはObjectクラスで定義されている
– インターフェースにおいて暗黙的なメソッド
抽象メソッドは0個
33
関数型インターフェース?
interface F {
Object clone();
}
34
関数型インターフェース?
interface F {
Object clone();
}
● Yes!
● cloneもObjectクラスで宣言されているが
protected
– Fではpublicで再宣言されている
35
関数型インターフェース(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.
36
関数型インターフェース(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
37
@FunctionalInterface
● 関数型インターフェースかどうか検査する
– コンパイル時
@FunctionalInterface
interface F {
boolean equals(Object o);
}
38
@FunctionalInterface
● 関数型インターフェースかどうか検査する
– コンパイル時
@FunctionalInterface
interface F {
boolean equals(Object o);
} @FunctionalInterface
^
Fは機能インタフェースではありません
インタフェース Fで抽象メソッドが見つかりません
エラー1個
39
匿名クラスからラムダ式へ
this.addActionListener(
new ActionListener(){
public void actionPerformed(
ActionEvent ae) {
//
}
})
40
匿名クラスからラムダ式へ
this.addActionListener(
new ActionListener(){
public void actionPerformed(
ActionEvent ae) {
//
}
})
addActionListenerの引
数から推論できる
41
匿名クラスからラムダ式へ
this.addActionListener(
new ActionListener(){
public void actionPerformed(
ActionEvent ae) {
//
}
})
実装するべきメソッド
も一意に定まる
42
ラムダ式
this.addActionListener(
(ActionEvent ae) -> {
//
})
● (仮引数) -> {メソッド本体}
● (int n1, int n2) -> {return n1+n2;}
43
ラムダ式
● 関数型インターフェースをインスタンス化
● (仮引数) -> {メソッド本体}
– 型推論で型が決まる
● 関数型インターフェースのインスタンスが
予期される場面で利用可
– ターゲット型
44
ターゲット型が曖昧な場合
Object o = () -> {};
– Objectが予期される
– 関数型インターフェースが予期されない
– 何を実装したらいいのかわからない
45
ターゲット型が曖昧な場合
Object o = (Runnable)() -> {};
– キャストを用いる
– Runnableが予期される
– 実装するべきインターフェースが分かる
46
ラムダ式の引数
this.addActionListener(
(ActionEvent ae) -> {
//
})
47
ラムダ式の引数
this.addActionListener(
(ActionEvent ae) -> {
//
})
引数の型も一意に定ま
る
48
ラムダ式の引数
this.addActionListener(
(ae) -> {
//
})
● 引数の型も省略可
● (n1, n2) -> {return n1+n2;}
49
ラムダ式の引数
this.addActionListener(
(ae) -> {
//
})
引数が一つで型が推論される
場合の()は不要
50
ラムダ式の引数
this.addActionListener(
ae -> {
//
})
● 引数が一つで型が省略される場合()不要
● n1 -> {return n1+5;}
51
ラムダ式の引数と_
● ラムダ式の引数としての_はコンパイルエラー
this.addActionListener( _ -> {/**/} );
– 他の言語での_は特殊な意味
– 混乱を招かないように利用不可に
– 将来の利用を見据え予約語に
● それ以外の_は警告に
52
ラムダ式のメソッド本体
(int n) -> {return n + 5;}
(n) -> {return n + 5;}
n -> {return n + 5;}
53
ラムダ式のメソッド本体
(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
54
ラムダ式のメソッド本体
(ActionEvent ae) -> {apply(ae);}
(ae) -> {apply(ae);}
ae -> {apply(ae);}
55
ラムダ式のメソッド本体
(ActionEvent ae) -> {apply(ae);}
(ae) -> {apply(ae);}
ae -> {apply(ae);}
● 戻り値がvoidでも,{;}を省略できる場合がある
(ActionEvent ae) -> apply(ae)
(ae) -> apply(ae)
ae -> apply(ae)
56
ラムダ式のスコーピング規則
1.ラムダ式には新しいスコープを導入しない
– 匿名クラスなどとは大きく違う
2.ローカル変数の参照はfinalな変数のみ
– 匿名クラスと同様
– 注:実質的にfinal(後ほど説明)
57
新しいスコープを導入しない
class Main {
void method() {
Runnable r = () ->
System.out.println(this);
}
}
58
新しいスコープを導入しない
class Main {
void method() {
Runnable r = () ->
System.out.println(this);
}
}
● ラムダ式内のthis=エンクロージングクラス
59
新しいスコープを導入しない
class Main {
void method(int n) {
Runnable r = () -> {int n;};
}
}
60
新しいスコープを導入しない
class Main {
void method(int n) {
Runnable r = () -> {int n;};
}
}
● 多重定義
● コンパイルエラー
61
新しいスコープを導入しない
class Main {
void method(int n) {
Function<Integer, Integer> f =
n -> n + 5;
}
}
● 多重定義
● コンパイルエラー
62
ローカル変数の参照
● 匿名クラスと同様
– finalな変数(実質的にfinal含む)
– 値の変更不可
63
ラムダ式の利用例
p -> p.getName()
s -> Integer.parseInt(s)
o -> list.add(o)
init -> new MyClass(init)
n -> new int[n]
● 引数を受け流すパターン
64
ラムダ式の利用例
p -> p.getName()
s -> Integer.parseInt(s)
o -> list.add(o)
init -> new MyClass(init)
n -> new int[n]
● 引数を受け流すパターン
● メソッド・コンストラクタ参照
65
メソッド・コンストラクタ参照
p -> p.getName()
s -> Integer.parseInt(s)
o -> list.add(o)
init -> new MyClass(init)
n -> new int[n]
● クラス名等::メソッド or new
Person::getName
Integer::perseInt
list::add
MyClass::new
int[]::new
66
マルチコアCPUコアライブラリ
ラムダ式・メソッド参照
実質的にfinal
型推論の強化
複合型キャスト
デフォルト実装
stat. intf. メソッド
67
実質的にfinal(Effectively final)
● 匿名クラスやラムダ式で
実質的にfinalな変数への参照が可能に
– コンパイラがfinal性を推論
● 実質的にfinalな変数
– final修飾されていない変数
– final修飾されてもエラーにならない変数
68
実質的にfinalの例
void method(final int n) {
final String str = “HelloFinal”
Runnable r = new Runnable() {
public void run() {
System.out.println(str + n);
}};
}
69
実質的にfinalの例
void method(int n) {
String str = “HelloEffectivelyFinal”
Runnable r = new Runnable() {
public void run() {
System.out.println(str + n);
}};
}
70
実質的にfinalの例
void method(int n) {
String str = “HelloEffectivelyFinal”
Runnable r = () ->
System.out.println(str + n);
}
71
実質的にfinalでない例
void method(int n) {
Runnable r = () ->
System.out.println(n);
n = 5;
}
ラムダ式から参照されるローカル変数は、
finalまたは事実上のfinalである必要があります
Runnable r = () -> System.out.println(n);
72
実質的にfinalでない例
void method(int n) {
Runnable r = () -> n++;
}
ラムダ式から参照されるローカル変数は、
finalまたは事実上のfinalである必要があります
Runnable r = () -> n++;
73
マルチコアCPUコアライブラリ
ラムダ式・メソッド参照
実質的にfinal
型推論の強化
複合型キャスト
デフォルト実装
stat. intf. メソッド
74
型推論の強化
● ターゲット型推論の強化
1.適用可能箇所の拡大
2.より正確な推論
75
ターゲット型推論?
● ターゲット型に基づく型推論
● JavaSE5(5.0)から存在
– メソッドジェネリクスの実型引数
– ダイアモンド演算子(JavaSE7)
76
ターゲット型
● ある式の型として予期される型のこと
● T t = expr;
– exprのターゲット型はT
77
ターゲット型が存在する文脈
● 変数宣言・・・ int n = …
● 割り当て・・・ n = …
● return文・・・ return …
● 配列初期化子・・・new String[]{...}
● 実引数・・・method(...)
● 条件式 ?:・・・bool ? … : …
● キャスト式 ・・・(Target)...
● ラムダ式の本体・・・() -> …
例 exprのターゲット型
変数宣言 int n = expr 変数の型(int)
割り当て n = expr 変数の型(nの型)
return文 return expr 戻り値の型
配列初期化子 new String[]{expr, ...} 配列の型(String)
実引数 m(expr, ...) 仮引数の型
条件式 cond ? expr : expr 透過された型
キャスト式 (String)expr String
ラムダ式の本体 () -> expr 戻り値の型
78
JavaSE7における適用可能箇所
メソッドジェネリクスの
実型引数
ダイアモンド演算子
変数宣言 ○ ○
割り当て ○ ○
return文 ○ ○
配列初期化子 ○ -
実引数 × ×
条件式 × ×
キャスト式 ○ ×
ラムダ式の本体
79
適用可能箇所の例(JavaSE7)
List<Integer> l = new ArrayList<>();
new ArrayList<T>()
new ArrayList<Integer>()
●
ArrayList<T> <: List<Integer>
– T = Integer
80
適用不可能箇所の例(JavaSE7)
● 実引数におけるターゲット型推論
printStrings(new ArrayList<>());
– void printStrings(List<String> l)
81
適用不可能箇所の例(JavaSE7)
● 実引数におけるターゲット型推論
printStrings(new ArrayList<Object>());
– void printStrings(List<String> l)
● コンパイルエラー
– Objectと推論される
82
適用不可能箇所の例(JavaSE7)
● 条件式におけるターゲット型推論
List<Integer> list = bool ?
Collections.emptyList() :
new ArrayList<>();
83
適用不可能箇所の例(JavaSE7)
● 条件式におけるターゲット型推論
List<Integer> list = bool ?
Collections.<Object>emptyList() :
new ArrayList<Object>();
● コンパイルエラー
– Objectと推論される
84
JavaSE8における適用可能箇所
メソッドジェネリクスの
実型引数
ダイアモンド演算子
変数宣言 ○ ○
割り当て ○ ○
return文 ○ ○
配列初期化子 ○ -
実引数 ○ ○
条件式 ○ ○
キャスト式 ○ ×(11/9現在)
ラムダ式の本体 ○ ○
85
適用可能になった例(JavaSE8)
● 実引数におけるターゲット型推論
printStrings(new ArrayList<>());
– void printStrings(List<String> l)
86
適用可能になった例(JavaSE8)
● 実引数におけるターゲット型推論
printStrings(new ArrayList<String>());
– void printStrings(List<String> l)
● 推論器が正しく働く
– ターゲット型よりStringと推論される
87
適用可能になった例(JavaSE8)
● 条件式におけるターゲット型推論
List<Integer> list = bool ?
Collections.emptyList() :
new ArrayList<>();
88
適用可能になった例(JavaSE8)
● 条件式におけるターゲット型推論
List<Integer> list = bool ?
Collections.<Integer>emptyList() :
new ArrayList<Integer>();
● 推論器が正しく働く
– ターゲット型よりIntegerと推論される
89
JavaSE8における適用可能箇所
ラムダ式・メソッド参照
変数宣言 ○
割り当て ○
return文 ○
配列初期化子 ○
実引数 ○
条件式 ○
キャスト式 ○
ラムダ式の本体 ○
90
2.より正確な推論
● 今までは簡易的な推論
● しばしば不正確な推論によりコンパイルエラー
– 複雑な場合
91
JavaSE7以前の推論
1.実引数の式の型を優先
2.実引数がない場合はターゲット型
92
ターゲット型推論が働く例
List<Number> list =
Arrays.asList();
java.util.Arrays#<T> List<T> asList(T...)
●
List<Number> =:= List<T>
– T = Number
93
不正確な推論の例(JavaSE7)
List<Number> list =
Arrays.asList(2, 5.5);
java.util.Arrays#<T> List<T> asList(T...)
94
不正確な推論の例(JavaSE7)
List<Number> list =
Arrays.<T>asList(2, 5.5);
●
T<:Object, T :>Integer,T:>Double(実引数より)
– T=Number & Comparable<...>
95
不正確な推論の例(JavaSE7)
List<Number> list =
Arrays.<Number & Comparable<...>>asList(2, 5.5);
● コンパイルエラー
– Number & Comparable<? extends Number &
Comparable<?>>と推論される
– List<Number & Comparable>をList<Number>に代入
96
JavaSE8以降の推論
● 実引数の型とターゲット型を加味
– より正確な型推論へ
97
先の例(JavaSE8の場合)
List<Number> list =
Arrays.asList(2, 5.5);
98
先の例(JavaSE8の場合)
List<Number> list =
Arrays.<T>asList(2, 5.5);
●
T<:Object, T :>Integer,T:>Double(実引数より)
●
T=Number(ターゲット型より)
– T=Number
99
先の例(JavaSE8の場合)
List<Number> list =
Arrays.<Number>asList(2, 5.5);
● 正しく推論器が働く
– Numberと推論される
100
マルチコアCPUコアライブラリ
ラムダ式・メソッド参照
実質的にfinal
型推論の強化
複合型キャスト
デフォルト実装
stat. intf. メソッド
101
複合型キャスト
キャスト式に複合型を
102
複合型?
● JavaSE5(5.0)から存在
– ジェネリクスの型境界(@型仮引数)
– <T extends Runnable & Cloneable>
● RunnableかつCloneable
● 型 & 型 & … & 型
● 合成型とも
103
複合型キャスト
● (型 & 型 & … & 型)式
● 主にラムダ式・メソッド参照と使用する
104
もしも複合型キャストがなかったら
● SerializableでRunnableなインターフェース
– 関数型インターフェース
– ラムダ式でインスタンス化したい
– インターフェースを定義する必要がある
105
もしも複合型キャストがなかったら
interface SRunnable implements
Runnable, Serializeable {}
sendRunnable((SRunnable) () -> {/* */});
106
もしも複合型キャストがなかったら
interface SRunnable implements
Runnable, Serializeable {}
sendRunnable((SRunnable) () -> {/* */});
107
複合型キャスト+ラムダ式
sendRunnable((Runnable & Serializable)
() -> {/* */});
● 型合成される
– マジキチ
108
マルチコアCPUコアライブラリ
ラムダ式・メソッド参照
実質的にfinal
型推論の強化
複合型キャスト
デフォルト実装
stat. intf. メソッド
109
<interface>
PublishedInterface
+already()
+exist()
+methods()
110
<interface>
PublishedInterface
+already()
+exist()
+methods()
PublisherImpl
+already()
+exist()
+methods()
AnotherImpl
+already()
+exist()
+methods()
UserImpl
+already()
+exist()
+methods()
111
<interface>
PublishedInterface
+already()
+exist()
+methods()
+newMethod()
PublisherImpl
+already()
+exist()
+methods()
AnotherImpl
+already()
+exist()
+methods()
UserImpl
+already()
+exist()
+methods()
112
<interface>
PublishedInterface
+already()
+exist()
+methods()
+newMethod()
PublisherImpl
+already()
+exist()
+methods()
AnotherImpl
+already()
+exist()
+methods()
UserImpl
+already()
+exist()
+methods()
113
インターフェースに拡張性を
● 新しいメソッドを加えても互換性を保つ
● デフォルト実装
– デフォルトの実装を提供する
– インターフェースに実装
– 実装が提供されない場合に使用される
114
デフォルト実装
interface Person {
Sex getSex();
default boolean isMan() {
return getSex() == Sex.MAN;
}
}
115
デフォルト実装
class PersonImpl implements Person {
public Sex getSex() {/*...*/}
// isManへの実装はなくてもOK
// Person#isManが使われる
}
116
デフォルト実装
class PersonImpl implements Person {
public Sex getSex() {/*...*/}
public boolean isMan() {/*...*/}
}
● オーバーライド可
117
デフォルト実装
● default修飾子
● publicメソッドとなる
– 既存のインターフェースメソッドと同様
● strictfp修飾のみ可
● 具象クラスで実装が提供されなくても無問題
● 拡張性を実現できた
– 新たな問題が・・・
118
実装の多重継承問題
119
多重継承
class BasicPerson {
public boolean isMan() {/*...*/}
}
class ComplexPerson extends BasicPerson
implements Person {
public Sex getSex() {/*...*/}
}
120
多重継承
BasicPerson
#isMan
Person
#isMan
ComplexPerson
#isMan
121
“Class always win”
122
クラスで定義された実装が
常に勝つ
123
Class always win
class BasicPerson {
public boolean isMan() {/*...*/}
}
class ComplexPerson extends BasicPerson implements
Person {
public Sex getSex() {/*...*/}
}
● BasicPerson#isManが使われる
– “Class always win”
124
親インターフェースの呼び出し
class ComplexPerson extends BasicPerson
implements Person {
public Sex getSex() {/*...*/}
public boolean isMan() {
return Person.super.isMan();
}
}
● インターフェース名.super.メソッド名(...)
125
クラスを介さない多重継承
interface Base1 {default void m() {}}
126
クラスを介さない多重継承
interface Base1 {default void m() {}}
interface Base2 {default void m() {}}
127
クラスを介さない多重継承
interface Base1 {default void m() {}}
interface Base2 {default void m() {}}
interface ExBase extends Base1, Base2 {}
128
多重継承
Base1#m Base2#m
ExBase#m
129
クラスを介さない多重継承
interface ExBase extends
Base1, Base2 {}
● コンパイルエラー
– オーバーライドして選択
130
クラスを介さない多重継承
interface ExBase extends
Base1, Base2 {
default void m() {
Base1.super.m();
}
}
137
多重継承は怖くない!!
● 大原則1:Class always win
– クラスで定義された実装が常に勝つ
● 大原則2:いつでもオーバーライドできる
– 親クラスでfinal修飾されてたら別
– インターフェースの実装を呼べる
138
Objectメソッドのデフォルト実装
● Objectで定義されたpublicメソッド
– そもそもデフォルトの実装
● Objectのメソッドのデフォルト実装は不可
– interface I {default String toString() {/* */}}
– コンパイルエラー
139
One more small change...
140
マルチコアCPUコアライブラリ
ラムダ式・メソッド参照
実質的にfinal
型推論の強化
複合型キャスト
デフォルト実装
stat. intf. メソッド
141
staticインターフェースメソッド
● staticなインターフェースメソッド
● 常にpublic修飾
– 他のインターフェースのメソッドと同様
● strictfp修飾可
– デフォルト実装と同様
142
staticインターフェースメソッドの例
interface Example {
static void method() {/* */}
}
143
staticインターフェースメソッドの例
interface Example {
static strictfp void method() {/* */}
}
● strictfp修飾可
144
staticインターフェースメソッドの継承
● 継承されない
– クラスメソッドと大きく違う
interface Example2 extends Example {}
Example2.method()はコンパイルエラー
145
Interesting Example
● publicでstaticなメソッド
– 人生で最初に書いたメソッド
146
Interesting Example
● publicでstaticなメソッド
– 人生で最初に書いたメソッド
public static void main(
String[] args)
147
main in Interface
interface EntryPoint {
public static void main(String[] args) {
/* ... */
}
}
● 正しく動く
148
マルチコアCPUコアライブラリ
ラムダ式・メソッド参照
実質的にfinal
型推論の強化
複合型キャスト
デフォルト実装
stat. intf. メソッド
149
No more 外部イテレーション
● 外部イテレーションは並列化困難
● 内部イテレーションベースのライブラリへ
– 並列化が容易に
150
外部イテレーション
● イテレーションが外にさらされている
– for,while文
for (Student s : students) {
}
151
内部イテレーションライブラリ
StreamAPI
152
StreamAPI
● java.util.stream.
Stream/IntStream/LongStream/DoubleStream
– ソースから生成される
– 非終端操作と終端操作でデータを弄る
– 並列化が容易
153
Collection
配列
BufferReader
etc...
Stream
IntStream
LongStream
DoubleStream
非終端操作
終端操作
j.u.stream.*Source
154
Collection
配列
BufferReader
etc...
Stream
IntStream
LongStream
DoubleStream
非終端操作
終端操作
j.u.stream.*Source
155
Make Streams
ソース メソッド 使用例
Collection Collection#stream list.stream()
配列 Arrays#stream Arrays.stream(args)
BufferReader BufferReader#lines br.lines()
n〜m-1までの数値 IntStream#range IntStream.range(n, m)
n〜mまでの数値 IntStream#rangeClosed IntStream.rangeClosed(n, m)
156
Collection
配列
BufferReader
etc...
Stream
IntStream
LongStream
DoubleStream
非終端操作
終端操作
j.u.stream.*Source
157
java.util.stream.
StreamAPI 要素の型
Stream<T> T(参照型)
IntStream int(プリミティブ型)
LongStream long(プリミティブ型)
DoubleStream double(プリミティブ型)
158
2 type of Streams
● Sequential Stream
– 直列で処理される
● Parallel Stream
– 並列で処理される
– 分割統治法(Fork/Join)
159
Change type of Stream
Sequential Stream
Parallel Stream
parallel() sequential()
160
Collection
配列
BufferReader
etc...
Stream
IntStream
LongStream
DoubleStream
非終端操作
終端操作
j.u.stream.*Source
161
非終端操作?
● filterやmapなど
– Streamを返すメソッド
● 終端操作が行われるまで処理されない
– 遅延される
162
主要な非終端操作
メソッド名 概要 使用例
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)
163
Collection
配列
BufferReader
etc...
Stream
IntStream
LongStream
DoubleStream
非終端操作
終端操作
j.u.stream.*Source
164
終端操作?
● forEachやreduceやcollectなど
– Streamを返さないメソッド
● 遅延されていた非終端操作を確定
165
主要な終端操作
メソッド名 概要 使用例
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()
166
0から10まで出力したい
for (int i = 0; i <= 10; i++) {
System.out.println(i);
}
167
forEach[終端操作]
T->void[j.u.function.Consumer<T>#void accept(T)]
● Stream<T>#forEach(T -> void)
– 各要素に処理を行なう
– s.forEach(t -> {/**/});
168
0から10まで出力したい
for (int i = 0; i <= 10; i++) {
System.out.println(i);
}
IntStream.rangeClose(0, 10)
.forEach(i -> System.out.println(i));
169
0から10まで出力したい
for (int i = 0; i <= 10; i++) {
System.out.println(i);
}
IntStream.rangeClose(0, 10)
.forEach(System.out::println);
170
0から10までの偶数を出力したい
for (int i = 0; i <= 10; i++) {
if (i % 2 == 0) {
System.out.println(i);
}
}
171
filter[非終端操作]
● Stream<T>#filter(T -> boolean)
– フィルタリング
– 各要素を引数に適用しtrueを返したもののみ残す
– s.filter(t -> t != null) // nullを除外
172
filter[非終端操作]
T->boolean[j.u.function.Predicate<T>#boolean test(T)]
173
0から10までの偶数を出力したい
IntStream.rangeClose(0, 10)
.filter(i -> i % 2 == 0)
.forEach(System.out::println);
174
Personのリストから名前を出力
for (Person p : persons) {
System.out.println(p.getName());
}
175
map[非終端操作]
● Stream<T>#map(T -> R)
– 写像・変換
– 各要素を引数に適用した結果のStreamを作る
– personStream.map(p -> p.getName())
176
map[非終端操作]
T -> R[java.util.function.Function<T, R>#R map(T)]
R
177
Personのリストから名前を出力
persons.stream()
.map(p -> p.getName());
.forEach(n -> System.out.println(n));
178
Personのリストから名前を出力
persons.stream()
.map(Person::getName);
.forEach(System.out::println);
179
Streamを横断するmap
Stream<T> IntStream
LongStream DoubleStream
#mapToObj
#mapToInt
#mapToLong
#mapToDouble
#mapToDouble
#mapToLong
#mapToInt
180
Personのリストから名前のリスト
List<String> names = new ArrayList<>();
for (Person p : persons) {
names.add(p.getName());
}
181
collect[終端処理]
● Stream<T>#collect(Collector<T, R>)
● #collect(() -> R, (R, T) -> void, (R, R) -> void)
– 集約処理を行なう
– stream.collect(Collectors.toList())
– strings.collect(StringBuilder::new,
StringBuilder::apped, StringBuilder::apped)
182
Personのリストから名前のリスト
persons.stream()
.map(Person::getName);
.collect(Collectors.toList())
183
Putting it together
学生のリスト(students)の内
2年生で
GPAが3.5以上ある学生の
学籍番号の
リストを生成する
184
Putting it together
List<StudentID> list = new ArrayList<>();
for (Student s : students) {
if (s.getGrade() == 2 &&
s.getGPA() >= 3.5) {
list.add(s.getID());
}
}
185
Putting it together
学生のリスト(students)の内
2年生で
GPAが3.5以上ある学生の
学籍番号の
リストを生成する
186
Putting it together
students.stream()
2年生で
GPAが3.5以上ある学生の
学籍番号の
リストを生成する
187
Putting it together
students.stream()
.filter(s -> s.getGrade() == 2)
GPAが3.5以上ある学生の
学籍番号の
リストを生成する
188
Putting it together
students.stream()
.filter(s -> s.getGrade() == 2)
.filter(s -> s.getGPA() >= 3.5)
学籍番号の
リストを生成する
189
Putting it together
students.stream()
.filter(s -> s.getGrade() == 2)
.filter(s -> s.getGPA() >= 3.5)
.map(Student::getID)
リストを生成する
190
Putting it together
students.stream()
.filter(s -> s.getGrade() == 2)
.filter(s -> s.getGPA() >= 3.5)
.map(Student::getID)
.collect(Collectors.toList())
191
Putting it together
students.stream().parallel()
.filter(s -> s.getGrade() == 2)
.filter(s -> s.getGPA() >= 3.5)
.map(Student::getID)
.collect(Collectors.toList())
192
Project Lambdaまとめ
● もともとはマルチコア対応
● 結果としては汎用的な仕様に
– ラムダ式等
– コアライブラリ
● よりスマートなコードへ
193
DeveloperPreview is now available!
● https://jdk8.java.net/download.html
● 最新のビルドb114
● Check these features by yourself!!
194
Thank you for your listening

More Related Content

Viewers also liked

プログラミング言語Clojureのニャンパスでの活用事例
プログラミング言語Clojureのニャンパスでの活用事例プログラミング言語Clojureのニャンパスでの活用事例
プログラミング言語Clojureのニャンパスでの活用事例sohta
 
あなたとAndroid 今すぐダウンロード!? Android開発で変わる SIerのJava技術事情について
あなたとAndroid 今すぐダウンロード!? Android開発で変わる SIerのJava技術事情についてあなたとAndroid 今すぐダウンロード!? Android開発で変わる SIerのJava技術事情について
あなたとAndroid 今すぐダウンロード!? Android開発で変わる SIerのJava技術事情についてShinichi Kozake
 
Android学ぶを君へ。生き抜くためのナレッジ共有
Android学ぶを君へ。生き抜くためのナレッジ共有Android学ぶを君へ。生き抜くためのナレッジ共有
Android学ぶを君へ。生き抜くためのナレッジ共有Shinobu Okano
 
Java web application testing
Java web application testingJava web application testing
Java web application testingTokuhiro Matsuno
 
DB設計でこだわりたい三つの要素
DB設計でこだわりたい三つの要素DB設計でこだわりたい三つの要素
DB設計でこだわりたい三つの要素Takahiro YAMADA
 
イミュータブルデータモデル(世代編)
イミュータブルデータモデル(世代編)イミュータブルデータモデル(世代編)
イミュータブルデータモデル(世代編)Yoshitaka Kawashima
 
Activity, Fragment, CustomView の使い分け - マッチョなActivityにさよならする方法 -
Activity, Fragment, CustomView の使い分け - マッチョなActivityにさよならする方法 -Activity, Fragment, CustomView の使い分け - マッチョなActivityにさよならする方法 -
Activity, Fragment, CustomView の使い分け - マッチョなActivityにさよならする方法 -Yuki Anzai
 
マテリアルデザインを用いたデザインリニューアル [フリル編]
マテリアルデザインを用いたデザインリニューアル [フリル編]マテリアルデザインを用いたデザインリニューアル [フリル編]
マテリアルデザインを用いたデザインリニューアル [フリル編]YUKI YAMAGUCHI
 
地域の魅力を伝えるツアーガイドAI
地域の魅力を伝えるツアーガイドAI地域の魅力を伝えるツアーガイドAI
地域の魅力を伝えるツアーガイドAIJubatusOfficial
 

Viewers also liked (9)

プログラミング言語Clojureのニャンパスでの活用事例
プログラミング言語Clojureのニャンパスでの活用事例プログラミング言語Clojureのニャンパスでの活用事例
プログラミング言語Clojureのニャンパスでの活用事例
 
あなたとAndroid 今すぐダウンロード!? Android開発で変わる SIerのJava技術事情について
あなたとAndroid 今すぐダウンロード!? Android開発で変わる SIerのJava技術事情についてあなたとAndroid 今すぐダウンロード!? Android開発で変わる SIerのJava技術事情について
あなたとAndroid 今すぐダウンロード!? Android開発で変わる SIerのJava技術事情について
 
Android学ぶを君へ。生き抜くためのナレッジ共有
Android学ぶを君へ。生き抜くためのナレッジ共有Android学ぶを君へ。生き抜くためのナレッジ共有
Android学ぶを君へ。生き抜くためのナレッジ共有
 
Java web application testing
Java web application testingJava web application testing
Java web application testing
 
DB設計でこだわりたい三つの要素
DB設計でこだわりたい三つの要素DB設計でこだわりたい三つの要素
DB設計でこだわりたい三つの要素
 
イミュータブルデータモデル(世代編)
イミュータブルデータモデル(世代編)イミュータブルデータモデル(世代編)
イミュータブルデータモデル(世代編)
 
Activity, Fragment, CustomView の使い分け - マッチョなActivityにさよならする方法 -
Activity, Fragment, CustomView の使い分け - マッチョなActivityにさよならする方法 -Activity, Fragment, CustomView の使い分け - マッチョなActivityにさよならする方法 -
Activity, Fragment, CustomView の使い分け - マッチョなActivityにさよならする方法 -
 
マテリアルデザインを用いたデザインリニューアル [フリル編]
マテリアルデザインを用いたデザインリニューアル [フリル編]マテリアルデザインを用いたデザインリニューアル [フリル編]
マテリアルデザインを用いたデザインリニューアル [フリル編]
 
地域の魅力を伝えるツアーガイドAI
地域の魅力を伝えるツアーガイドAI地域の魅力を伝えるツアーガイドAI
地域の魅力を伝えるツアーガイドAI
 

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
 
Brand new Data Processing - StreamAPI
Brand new Data Processing - StreamAPIBrand new Data Processing - StreamAPI
Brand new Data Processing - StreamAPIbitter_fox
 
徹底解説!Project Lambdaのすべて in Fukuoka #j8fk
徹底解説!Project Lambdaのすべて in Fukuoka #j8fk徹底解説!Project Lambdaのすべて in Fukuoka #j8fk
徹底解説!Project Lambdaのすべて in Fukuoka #j8fkbitter_fox
 
徹底解説!Project Lambdaのすべて リターンズ[祝Java8Launch #jjug]
徹底解説!Project Lambdaのすべて リターンズ[祝Java8Launch #jjug]徹底解説!Project Lambdaのすべて リターンズ[祝Java8Launch #jjug]
徹底解説!Project Lambdaのすべて リターンズ[祝Java8Launch #jjug]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 (9)

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大阪
 
Brand new Data Processing - StreamAPI
Brand new Data Processing - StreamAPIBrand new Data Processing - StreamAPI
Brand new Data Processing - StreamAPI
 
徹底解説!Project Lambdaのすべて in Fukuoka #j8fk
徹底解説!Project Lambdaのすべて in Fukuoka #j8fk徹底解説!Project Lambdaのすべて in Fukuoka #j8fk
徹底解説!Project Lambdaのすべて in Fukuoka #j8fk
 
徹底解説!Project Lambdaのすべて リターンズ[祝Java8Launch #jjug]
徹底解説!Project Lambdaのすべて リターンズ[祝Java8Launch #jjug]徹底解説!Project Lambdaのすべて リターンズ[祝Java8Launch #jjug]
徹底解説!Project Lambdaのすべて リターンズ[祝Java8Launch #jjug]
 
RCC LT 2013 Javaを日本語で書けるようにしてみた(言語処理)
RCC LT 2013 Javaを日本語で書けるようにしてみた(言語処理)RCC LT 2013 Javaを日本語で書けるようにしてみた(言語処理)
RCC LT 2013 Javaを日本語で書けるようにしてみた(言語処理)
 
Lt (コピー)
Lt (コピー)Lt (コピー)
Lt (コピー)
 

Recently uploaded

業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)Hiroshi Tomioka
 
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。iPride Co., Ltd.
 
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。iPride Co., Ltd.
 
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
LoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイスLoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイス
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイスCRI Japan, Inc.
 
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアルLoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアルCRI Japan, Inc.
 
新人研修 後半 2024/04/26の勉強会で発表されたものです。
新人研修 後半        2024/04/26の勉強会で発表されたものです。新人研修 後半        2024/04/26の勉強会で発表されたものです。
新人研修 後半 2024/04/26の勉強会で発表されたものです。iPride Co., Ltd.
 
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)NTT DATA Technology & Innovation
 

Recently uploaded (7)

業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
 
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
 
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
 
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
LoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイスLoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイス
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
 
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアルLoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
 
新人研修 後半 2024/04/26の勉強会で発表されたものです。
新人研修 後半        2024/04/26の勉強会で発表されたものです。新人研修 後半        2024/04/26の勉強会で発表されたものです。
新人研修 後半 2024/04/26の勉強会で発表されたものです。
 
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
 

徹底解説!Project Lambdaのすべて[JJUG CCC 2013 Fall H-2]