気軽に楽しくプログラムと遊ぶ

自分が興味があってためになるかもって思う情報を提供しています。

Java8 ラムダ式でよく利用する関数型インターフェース

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

  • 単一メソッドを持つインターフェース群
  • ラムダ 式で利用するのに都合がいい
  • SE8からjava.util.functionパッケージに追加された

ラムダ式を引数として取る場合に、関数型インターフェースを指定して受け取る。
ラムダ式の種類毎に用意された入れ物が関数型インターフェースとも言える。

// 例として、filter()は関数型インターフェースを引数に取る
numbersList.stream().filter((i) -> { return i > 0; })

関数型インターフェースとして使用頻度の高いFuction、Consumer、Predicateを見ていく。

Function<T,R>

Function<T,R>のTはメソッドの引数の型、Rは戻り値の型を指定する。
メソッドはR apply(T)を使って、定義した処理に引数を渡して、結果を返却する。

// Functionにラムダ 式(メソッドオブジェクトのようなもの)を代入
Function<Interger, Integer> calcPlusOne = (i) -> { return i + 1 };

// calcPlusOneを使ってみる
Integer result =  calcPlusOne.apply(1); // result = 2

Function<T,R>を引数に取るStreamAPIのメソッドmap

ListString impNum = numbersList.stream().filter((i) -> { return i >= 0; })
                    .map((i) -> { return "*" + i + "*"; })
                    .forEach((s) -> { System.out.print(s + " "); });
                    // *2* *0* *8* 

Function<T,R>は、引数が1つで処理結果を返却したい場合のラムダ式に用いる。

Consumer

ConsumerのTはメソッドの引数の型を指定する。
メソッドはvoid accept(T)を使って、定義した処理に引数を渡して、結果を返却する。

Consumer<String> greeting = (name) -> { System.out.println(name + "さん、おはようございます。"); };
greeting.accept("太郎"); // 太郎さん、おはようございます。

Consumerを引数に取るStreamAPIのメソッドforEach

numbersList.stream().forEach((i) -> { System.out.print(i + " "); }); // Eachは要素の数だけ繰り返す。

Consumerは、引数が1つで処理結果を返却しない場合のラムダ式に用いる。

Predicate

PredicateのTはメソッドの引数の型を指定する。 メソッドは boolean test(T)を使って、定義した処理に引数を渡して、結果を返却する。

Predicate<T> checkBigNum = (num) -> { return num > 10000}
boolean result = checkBigNum(10); // result = false

Predicateを引数に取るStreamAPIのメソッドfilter

// numbersListに-1 と2と8あり
numbersList.stream().filter((i) -> { return i > 0; }) // 負の数を除外
                    .forEach((i) -> { System.out.print(i + " "); });
                    // 2 8 

Predicateは、引数が1つでbooleanを返却する場合のラムダ式に用いる。

Pythonの負荷テストツール Locust

Pythonで負荷テストコードを記載するLocustについて記載します。

特徴

  • シナリオを Python で記述
  • 分散&スケーラブル
  • Web ベース管理画面
  • 高いカスタマイズ性

本家サイト

動かしてみる

テストケース

from locust import HttpUser, TaskSet, task, between, constant

class UserBehavior(TaskSet):
    @task(1)
    def profile(self):
        self.client.get("/sample", verify=False) # パスにはプロトコルやホストは記載しない

class WebsiteUser(HttpUser):
    tasks = {UserBehavior:1}
    min_wait = 5000 #タスクの実行間隔はmin_waitとmax_waitの間のランダム値となる
    max_wait = 15000 # 上書き時に記述。デフォルトは min_wait=500, max_wait=1500 単位はミリ秒

起動

locust
# 以下の省略版
#  locust -f ./locustfile.py

http://localhost:8089でWeb UIにアクセス可能

f:id:tamata78:20210818184631p:plain

参考サイト

MacOS Python3系インストール

Pythonバージョン管理ツールのpyenvを入れて、3系のPythonをインストール&適用させていきます。

pyenvをインストール

brew install pyenv

pyenvの設定(シェルがzshの場合)

echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.zshrc
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.zshrc
echo 'eval "$(pyenv init -)"' >> ~/.zshrc
source ~/.zshrc

Pythonインストール

pyenv install --list

pyenv install 3.9.6

インストール済pythonの確認

pyenv versions 
* system (set by /Users/UserName/.pyenv/version)
  3.9.6

ローカルへのpythonの適用

pyenv global 3.9.6

python3 --version
Python 3.9.2

python3 hello.py #Pythonファイルの実行

JSON用のgrepみたいなjqコマンド

JSONを便利に編集できるjqコマンドできる基礎的なことを書いておきます。

マニュアル、参考URL

公式マニュアルをみておくと幸せになれる。
jq Manual (development version)

ここに書いていることでメモしておきたいことを書いていきます。
jq コマンドを使う日常のご紹介 - Qiita

コマンド使い方

.がルート{}を表します。

整形

% echo '{"items":[{"item_id":1,"name":"たろう"},{"item_id":2,"name":"はなこ"}]}' \
| jq .

{
  "items": [
    {
      "item_id": 1,
      "name": "たろう"
    },
    {
      "item_id": 2,
      "name": "はなこ"
    }
  ]
}

列取得

% echo '{"items":[{"item_id":1,"name":"たろう"},{"item_id":2,"name":"はなこ"}]}' 
| jq '.items[]..name'   
"たろう"
"はなこ"

# ダブルコートを消すには -r をつける
% echo '{"items":[{"item_id":1,"name":"たろう"},{"item_id":2,"name":"はなこ"}]}' \   [14:48:38]
| jq -r '.items[].name'
たろう
はなこ

フィルタ(パイプみたいなもの)

'.items[]'までの結果を.nameへ渡す。

% echo '{"items":[{"item_id":1,"name":"たろう"},{"item_id":2,"name":"はなこ"}]}' \   [14:48:44]
| jq -r '.items[] | .name'
たろう
はなこ

パイプの後で編集

項目の順序やプロパティー名を変更、配列にしたりなど

% echo '{"items":[{"item_id":1,"name":"たろう"},{"item_id":2,"name":"はなこ"}]}' \   [14:50:27]
| jq -r '.items[] | {name2: .name, item_id2: .item_id}'
{
  "name2": "たろう",
  "item_id2": 1
}
{
  "name2": "はなこ",
  "item_id2": 2
}

他にもいろいろありそうだけど、一旦ここまで。

Kotlin 正規表現

下記の例を貼らせて頂きました。
Kotlinの正規表現の使い方 | 寝室コンピューティング

// a,b,cのうちいずれかにマッチ
val regex = Regex(pattern = "[abc]")

// Raw Stringはエスケープ不要
"""\d"""

// 普通の文字列だとエスケープが必要
"\\d"

// 文字列に数字が含まれているかチェックする
val target = "1 apple. 2 bananas."
val regex = Regex("""\d""")

val isMatched = regex.containsMatchIn(target)
print(isMatched) 

val match = regex.find(target)
print(match?.value)
// 結果:1

val matches = regex.findAll(target)
matches?.forEach { match -> print("${match.value} ") }
// 結果:1 2 

val target = "090-1111-2222"
val regex = Regex("""(\d+)-(\d+)-(\d+)""")

val match = regex.find(target)
 
match?.groups?.forEach { group -> println("${group?.value}") }
/* 以下が格納されている
group[0]:090-1111-2222
group[1]:090
group[2]:1111
group[3]:2222
*/

Mockito 基礎文法

Mockitoでパッとわからなかった書き方について書いていきます。

戻り値なしメソッド

何も返さないメソッドが指定インスタンスと引数のときにMock化されます

Mockito.doNothing().when(モックインスタンス).メソッド(任意の引数);

privateメソッド、staticメソッド

MockitoではMock化できない。実現したい場合、PowerMockを使う

モックオブジェクトの検証(verify)

  • @mock @spyどちらのオブジェクトに対しても使用可能
  • 呼ばれた回数の検証ができる

指定回数呼ばれているかtimes

sample1.method1(10);
sample1.method1(20);
sample1.method1(20);    
verify(sample1,times(2)).method1(20);         // OK 
verify(sample1,times(3)).method1(20);         // エラー

指定回数呼ばれているかatLeastOnce atLeast atMost never

verify(sample1,atLeastOnce()).method1(0); // 最後に呼ばれたメソッドと引数が一致で正常
verify(sample1, atLeast(2)).method1(20);   // 2回以上でOK
verify(sample1, atMost(2)).method1(20);    // 2回以下でOK
verify(sample1,never()).method1(20);       // 0回で正常 (times(0))と等価