トップ・ページの表示 注意書きの表示 掲示板に書き込む前に必ず この ”注意書き”を お読み下さい.

"沙羅"

★この掲示板は書き込みを停止いたしました 。
記事の書き込みはリンク・ページの表示 http://ashtarte.hotcom-web.com/utf8/smt.cgi?r+rpr/ を ご利用 下さい。

   
   

ページの表示順:{ 新しい順/ 古い順}.
初期・ページの表示・位置:{ 先頭ページ/ 末尾ページ}.
1ページ内のスレッド表示数:







<Number>: [000000E0]  <Date>: 2023/10/24 18:57:13
<Title>: Javaの小技
<Name>: amanojaku@管理人

■知ってお得な機能

プリミティブ型、オブジェクト型(参照型) オートボクシング、アンボクシング
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()))
);

Block( Address 00000785 Identity 000000E0 )






ページの表示順:{ 新しい順/ 古い順}.
初期・ページの表示・位置:{ 先頭ページ/ 末尾ページ}.
1ページ内のスレッド表示数:

   
   

管理者用 Password:

  




SMT Version 8.022(+A) Release M6.
Author : amanojaku.