■知ってお得な機能
プリミティブ型、オブジェクト型(参照型) オートボクシング、アンボクシング
http://qiita.com/chihiro/items/870eca6e911fa5cd8e58
関数型、メソッド参照、ラムダ式、ストリーム処理
https://qiita.com/lrf141/items/98ffbeaee42d30cca4dc
関数型プログラミングで行こう ~ みんな大好きJavaから入る関数型の入り口の入り口
http://tercel-tech.hatenablog.com/entry/2014/12/29/173711
[Java] Java8のラムダに超入門(書き方、関数型インターフェース、独自に定義、ラムダ受け取り処理)
https://www.yoheim.net/blog.php?q=20160410
[java][java8]Java 8を関数型っぽく使うためのおまじない
http://d.hatena.ne.jp/nowokay/20130501
>カリー化
>さて、2引数以上の関数は甘えと書きましたが
↑(知っておいて損は無いかもしれないが)ラムダ式は丸括弧で囲めば2引数以上も可能なのでカリー化は特に必要ない。
■GUIコンポーネントの設定はイベント・ディスパッチ・スレッドで設定しなければならなくなったようです。
昔はイベントもメイン・スレッドでしたが、(知らぬ間に)イベントがイベント・ディスパッチ・スレッドに分離されたようで、GUIコンポーネントの設定もイベント・ディスパッチ・スレッドで設定しなければならなくなりました、つまりメイン・スレッドでのGUIコンポーネントの設定はNGになってしまいました。
対処法は定型処理で記述できるので簡単に対応できます(下記)。
Java Swing/「JFrameスケルトン・テンプレート」(7)
http:../utf8/smt.cgi?r+sara/&bid+00000428&tsn+00000428&bts+2021/01/20%2016%3A41%3A48&
■スレッドは「Concurrency Utilities」のスレッドが強く推奨されます。
(知らぬ間に)古いタイプのThreadが非推奨に?、(正式な非推奨では無いかもしれないが)そんなクズみたいなモノを何時までも使わないでくれよ、って話。
下記 動画を参照して下さい、青色がCUPの未使用率、緑色がCUPの使用率だと思われます。
その動画のコンソール入力に注目すると、「ConcurrencyTest」を実行すると、CUPの使用率が ほぼ100%になり、圧倒的に効率が上がります(逆に言うと古いタイプのThreadが如何にクズかと言うことでも有りますが)。
なお Android Javaの場合は、中身は素のJavaとは別モノなのでスレッドは「Concurrency Utilities」を使わなくてもおkです。
Concurrency Utilities for EE 7
https://yoshio3.com/2013/05/15/concurrency-utilities-for-ee-7/
■「ストリームAPI、ラムダ式、メソッド参照」などの おおまかなデモ紹介(詳細な解説はしていませんので悪しからず)。
※ここで記載しているStream APIはIO系のStreamとは別物ですので ご注意 下さい。
※Stream APIのセールス・ポイントとして(データ量が膨大な場合は)Parallel化によるパフォーマンスの向上の"可能性"があります(データ量が少ないとParallel化によるオーバーヘッドでパフォーマンスが悪化するので注意が必要です)。
※Parallel化しても、流石にforEach()メソッド内なら順番に依存するだろうと甘く考えていましたが、実際にParallel化したら順番に依存しませんでした(^_^;マジか)。
順番に依存させたい場合はforEachOrdered()メソッドを使えば良いようです。
※メソッド参照は(メソッドの)仮引数の型(関数型インタフェース)を無視して、実引数として設定が可能と言う意味不明な仕様となっています。
それまでJavaは型を厳格に遵守してきたにも係わらず、メソッド参照で それを完全に覆しています(それなら多重継承も出来るようにしろよって話だが…)。
メソッド参照は(メソッドの)仮引数の関数型インタフェースのメソッドのシグネチャと一致しているだけでOK。
メソッド参照用のクラスを作成する場合は、関数型インタフェースをimplementsする必要も有りませんし、メソッド参照用のメソッド名と関数型インタフェースのメソッド名を一致させる必要すら有りません。、
●使用したパッケージ
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
import java.util.stream.Collectors;
import java.util.Collections;
import java.util.Comparator;
import java.util.concurrent.atomic.AtomicInteger;
●初期設定
int num, min, max;
long knum;
double dnum;
int[] ia;
int[] iarray;
int[][] iarray2;
Integer[] oiarray;
List list;
List<Character> clist;
ArrayList<Character> calist;
ArrayList<String> salist;
iarray = new int[] {1, 7, 3, 2, 0, 5};
iarray2 = new int[][]{{1, 2, 3}, {7, 8, 9}};
oiarray = new Integer[] {1, 7, 3, 2, 0, 5};
calist = new ArrayList<Character>(Arrays.asList('Q', 'W', 'E', 'R', 'T', 'Y'));
salist = new ArrayList<String>(Arrays.asList("hoge", "fuga", "piyo", "mogera"));
●「配列、コレクション(List系)」の表示
◆Arrays.toString()
System.out.println(Arrays.toString(iarray));
▲実行結果
[1, 7, 3, 2, 0, 5]
◆拡張for文
for (int i : iarray) {
System.out.print("<" + i + ">,");
}
System.out.println();
for (char c : calist) {
System.out.print("<" + c + ">,");
}
System.out.println();
for (String s : salist) {
System.out.print("<" + s + ">,");
}
System.out.println();
▲実行結果
<1>,<7>,<3>,<2>,<0>,<5>,
<Q>,<W>,<E>,<R>,<T>,<Y>,
<hoge>,<fuga>,<piyo>,<mogera>,
◆(Arrays.stream()メソッド)、forEach()メソッド、ラムダ式
Arrays.stream(iarray).forEach(i -> System.out.print("<" + i + ">,"));
System.out.println();
calist.forEach(c -> System.out.print("<" + c + ">,"));
System.out.println();
salist.forEach(s -> System.out.print("<" + s + ">,"));
System.out.println();
▲実行結果
<1>,<7>,<3>,<2>,<0>,<5>,
<Q>,<W>,<E>,<R>,<T>,<Y>,
<hoge>,<fuga>,<piyo>,<mogera>,
◆forEach()メソッド、メソッド参照
salist.forEach(System.out::println);
▲実行結果
hoge
fuga
piyo
mogera
◆(Arrays.stream()メソッド、stream()メソッド)、(mapToObj()メソッド、map()メソッド)、ラムダ式、forEach()メソッド、メソッド参照
Arrays.stream(iarray).mapToObj(i -> "<" + i + ">,").forEach(System.out::print);
System.out.println();
calist.stream().map(c -> "<" + c + ">,").forEach(System.out::print);
System.out.println();
salist.stream().map(s -> "<" + s + ">,").forEach(System.out::print);
System.out.println();
▲実行結果
<1>,<7>,<3>,<2>,<0>,<5>,
<Q>,<W>,<E>,<R>,<T>,<Y>,
<hoge>,<fuga>,<piyo>,<mogera>,
◆(Arrays.stream()メソッド、stream()メソッド)、(mapToObj()メソッド、map()メソッド)、(メソッド参照)、collect()メソッド、Collectors.joining()メソッド
※print文をStreamの外に出している。
System.out.println(Arrays.stream(iarray).mapToObj(String::valueOf).collect(Collectors.joining(",")));
System.out.println(calist.stream().map(String::valueOf).collect(Collectors.joining(",")));
System.out.println(salist.stream().collect(Collectors.joining(",")));
▲実行結果
1,7,3,2,0,5
Q,W,E,R,T,Y
hoge,fuga,piyo,mogera
◆Arrays.stream()メソッド、mapToObj()メソッド、collect()メソッド、Collectors.joining()メソッド
※10個づつに分割して表示する。
※print文をStreamの外に出している。
AtomicInteger ac = new AtomicInteger();
ac.set(0);
System.out.println(Arrays.stream(iarray).
mapToObj(v -> v + (ac.getAndIncrement() % 10 != 9 ? ", " : ";"+System.lineSeparator())).
collect(Collectors.joining()));
●プリミティブ型・配列をListに変換
◆プリミティブ型1次元配列をListに変換
list = Arrays.stream(iarray).mapToObj(Integer::valueOf).collect(Collectors.toList());
System.out.println(list);
◆プリミティブ型2次元配列をListに変換
list = Arrays.stream(iarray2).map(L1 ->Arrays.stream(L1).
mapToObj(Integer::valueOf).collect(Collectors.toList())).collect(Collectors.toList());
System.out.println(list);
●「配列、コレクション(List系)」のソート
◆Arraysクラスを使ったプリミティブ型・配列用 昇順Sort
※降順ソートが出来ない謎仕様(当然、カスタム化もできない)、降順ソートをしたい場合はStreamで処理しなければならない。
ただし、オブジェクト配列ならComparatorインターフェイスでカスタム化が可能。
Arrays.sort(iarray); // 昇順
◆Arraysクラスを使ったオブジェクト配列用 カスタムSort(通常版)
Arrays.sort(oiarray, new Comparator<Integer>() {
@Override
public int compare(Integer i1, Integer i2) {
return i1-i2;
}
});
◆Arraysクラスを使ったオブジェクト配列用 カスタムSort(ラムダ式版、複数行記述可)
Arrays.sort(oiarray, (i1, i2) -> {
return i1-i2;
});
◆Arraysクラスを使ったオブジェクト配列用 カスタムSort(ラムダ式版、1行記述時の省略形)
※1行のみの場合に限り、波括弧もreturnすら省略可能。
Arrays.sort(oiarray, (i1, i2) -> i1-i2);
◆Streamを使ったプリミティブ型・配列用 降順Sort
※Comparator.naturalOrder()で昇順Sortも可能、ラムダ式でカスタム化も可能、ただし たかが降順Sortで こんなに長ったらしいのがイマイチ。
ia = Arrays.stream(iarray).boxed().sorted(Comparator.reverseOrder()).mapToInt(Integer::intValue).toArray();
◆Streamを使った(Collection系)簡易Sort(昇順)
※Comparator.reverseOrder()で降順Sortも可能、ラムダ式でカスタム化も可能。
list = (List)salist.stream().sorted(Comparator.naturalOrder()).collect(Collectors.toList());
System.out.println(list);
◆Collectionsクラスを使った(Collection系)簡易Sort(昇順)
※Comparator.reverseOrder()で降順Sortも可能。
Collections.sort(salist, Comparator.naturalOrder());
◆Collectionsクラスを使った(Collection系)カスタムSort(通常版)
Collections.sort(calist, new Comparator<Character>() {
@Override
public int compare(Character c1, Character c2) {
return c1 - c2;
}
});
◆Collectionsクラスを使った(Collection系)カスタムSort(通常版)
※文字列の場合は返り値用の演算にcompareTo()メソッドを使っていることに注意。
Collections.sort(salist, new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return s1.compareTo(s2);
}
});
◆Collectionsクラスを使った(Collection系)カスタムSort(ラムダ式版、複数行記述可)
Collections.sort(salist, (s1, s2) -> {
return s1.compareTo(s2);
});
◆Collectionsクラスを使った(Collection系)カスタムSort(ラムダ式版、1行記述時の省略形)
※1行のみの場合に限り、波括弧もreturnすら省略可能。
Collections.sort(salist, (s1, s2) -> s1.compareTo(s2));
●プリミティブ型・配列内の3以上の要素をプリミティブ型・配列に格納する。
Arrays.stream()メソッド、filter()メソッド、toArray()メソッド
ia = Arrays.stream(iarray).filter(i -> 3 <= i).toArray();
Arrays.stream(ia).forEach(System.out::println);
▲実行結果
7
3
5
●全ての半角文字をList化して表示
// int型(プリミティブ型)によるStream。
// rangeClosed()メソッドで「初期値、終端値」を設定(増分は1)。
// mapToObj()メソッドによりchar型(プリミティブ型)がCharacter型(ラッパークラス)にオートボクシングされ、
// StreamはCharacter型(ラッパークラス)になる。
// collect(Collectors.toList())でList化。
min = 32;
max = 126;
clist = IntStream.rangeClosed(min, max).mapToObj(i -> (char) i).collect(Collectors.toList());
System.out.println(clist);
// int型(プリミティブ型)によるStream。
// iterate()メソッドで「初期値、増減値」を設定。
// limit()メソッドで「初期値からの相対的な限界値(ゼロ・スタート)」を設定。
// mapToObj()メソッド内でchar型(プリミティブ型)にキャストされているので、
// オートボクシングによりStreamはCharacter型(ラッパークラス)になる。
// collect(Collectors.toList())でList化。
min = 32;
max = 126;
clist = IntStream.iterate(min, i -> i + 1).limit(max - (min - 1)).mapToObj(i -> (char) i).collect(Collectors.toList());
System.out.println(clist);
// 普通のStream。
// iterate()メソッドで「初期値、増減値」を設定。
// ※iterate()メソッド内の引数(演算)がchar型(プリミティブ型)にキャストされているので、
// オートボクシングによりStreamはCharacter型(ラッパークラス)になる。
// limit()メソッドで「初期値からの相対的な限界値(ゼロ・スタート)」を設定。
// collect(Collectors.toList())でList化。
// ※ラッパークラスによる数値演算なので効率は悪い(あくまでもStreamの用法デモ)。
min = 32;
max = 126;
clist = Stream.iterate((char) min, i -> (char) (i + 1)).limit(max - (min - 1)).collect(Collectors.toList());
System.out.println(clist);
▲実行結果
※3つとも同じ。
[ , !, ", #, $, %, &, ', (, ), *, +, ,, -, ., /, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, :, ;, <, =, >, ?, @, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, [, \, ], ^, _, `, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, {, |, }, ~]
●100からnum回2倍づつした値の合計
下記は「100+200+400+800+1600=3100」
num = 5;
System.out.println(IntStream.rangeClosed(1, num).reduce(0, (a, v) -> a*2 + 100));
●「1~num」までの11で割り切れる数値の合計
num = 9878;
System.out.println(IntStream.rangeClosed(1, num).filter(i -> (i % 11) == 0).reduce(0, (a, v) -> a + v));
▲実行結果
4440161
●num!(階乗)
※階乗の場合、入力自体はintでも全く問題ない。
// long型(プリミティブ型)による演算
num = 10; // int
knum = LongStream.rangeClosed(1, num).reduce(1, (a, v) -> a * v);
System.out.println(knum);
// double型(プリミティブ型)による演算
num = 25; // int
dnum = IntStream.rangeClosed(1, num).asDoubleStream().reduce(1.0, (a, v) -> a * v);
System.out.println(dnum);
// Double型(ラッパークラス)による演算、ラッパークラスによる数値演算なので効率は悪い(あくまでもStreamの用法のデモ)。
// ※iterate()メソッド内の演算がdouble型(プリミティブ型)になっていることに注意、オートボクシングによりStreamはDouble型(ラッパークラス)になる。
num = 25; // int
dnum = IntStream.rangeClosed(1, num).asDoubleStream().reduce(1.0, (a, v) -> a * v);
System.out.println(dnum);
▲実行結果
3628800
1.5511210043330986E25
1.5511210043330986E25
●2次元配列
◆numで初期化された「行6x列30」の2次元int配列の生成
num = -1;
int[][] hoge = IntStream.rangeClosed(1, 6).mapToObj(i -> IntStream.generate(() -> num).limit(30).toArray()).toArray(int[][]::new);
◆2次元プリミティブ型(データ型)配列の列をList化して表示
Arrays.stream(hoge).forEach(ar -> System.out.println(Arrays.stream(ar).mapToObj(String::valueOf).collect(Collectors.toList())));
◆2次元プリミティブ型(データ型)配列の列をjoining()メソッドで連結させ表示
Arrays.stream(hoge).forEach(ar -> System.out.println(Arrays.stream(ar).mapToObj(String::valueOf).collect(Collectors.joining(" "))));
◆2次元プリミティブ型(データ型)配列を2つのjoining()メソッドで完全文字列化して表示
※print文をStreamの外に出している。
System.out.println(
Arrays.stream(hoge).map(a ->
Arrays.stream(a).mapToObj(String::valueOf).collect(Collectors.joining(" "))
).collect(Collectors.joining(System.lineSeparator()))
);
|
|