Intellijのgoogle-java-format plugin を外した.

ちょっと思うところがあって、google-java-format plugin を外した。
このプラグインがあると、結構強制力が強くて、indent4 にしたいときにできなかったり、import文を変えたかったりしたときにできなかったりとか・・・あったので、外しました…

ただそれだけ…

https://plugins.jetbrains.com/plugin/8527-google-java-format

Java8の@FunctionalInterfaceを使う

関数インターフェースのPredicateとかFunctionがあるのであんまり使わないけど、引数とか3つ以上のものはないのでつくる必要がある。

基本的に抽象メソッドを1つしかもっていなければOK。defaultメソッドはいくつもっていてもOKです。(ラムダ式のときに何を使うかわからなくなっちゃうからかなと)

@FunctionalInterface
interface SampleInterface {
      boolean filter(String a);
}

こんな感じでカンタンに作れる

使うときはこんな感じでカンタンに使える。

SampleInterfacle sampleFilter = s -> "a".equals(s);
sampleFilter.filter("a");

なんかもうカンタン過ぎますね

ちなみに引数3つは、こんな感じ

@FunctionalInterface
interface SampleInterface {
      boolean filter(String a, String b, String c);
}

SampleInterfacle sampleFilter = (s, t , u)  -> "a".equals(s);
sampleFilter.filter("a","b","c");

こんな感じで使える。なんかもうカンタン過ぎますね。みんなもっと使いましょう!

Javaの関数インターフェース再入門

Javaのよく使ってる関数インターフェース群をまとめようかとおもう。
現場ごとに説明のためのドキュメントを書くのがしんどくなってきたからというのが本音かも。

predicate

断言するって意味。戻り値はBoolean。
引数1つとって

Predicate<String> matchA = s -> s.matches(".*a.*");  // 'a'があればtrue
Predicate<String> matchB = s -> s.matches(".*b.*"); // 'b'があればtrue
Predicate<String> noA = matchA.negate(); // 'a'があったらfalse

// 合成
Predicate<String> ab = matchA.and(matchB); // 'a'と'b'があったらtrue
Predicate<String> ab = matchA.or(matchB); // 'a'または'b'があったらtrue

実行はtest(T)でできる。カンタン。streamのfilterとかで使える。テストもカンタン。

matchA.test("a");

これで実行できる。

ちなみに2つ引数とることもできる

BiPredicate<String,String> matchAB = (s,t) -> s.matches(".*a.*") && t.matches(".*a.*");

suppplier

供給するって意味

引数なし、戻り値あり。引数ないけど、それ単体で何かが発生する。
なにかと組み合わせてデータ流す感じかな

Supplier<String> supplier = () -> {
     SecureRandom random = new SecureRandom();
     return String.valueOf(random.nextInt());
};

ランダムintを返却する

supplier.get()

consumer

消費するって意味。
実際に引数とって、そのあと処理する。戻り値なし。

下記のような感じ

Consumer<String> show = s -> System.out.println(s);

下記のように使う

s.accept("s");

2つ引数とることも可能

BiConsumer<String,Integer> biShow = (s,i) -> {
    System.out.println(s);
    System.out.println(i);
};

Function

機能として使える関数インターフェース

引数と戻り値を持てる。
引数2つまで持てるものもある。(BiFunction)

下記のように定義できる

Function<Integer,String> exchangeString = t -> String.valueOf(t);
BiFunction<Integer,Integer,String> biExchange = (t,u) -> String.valueOf(t + u);

下記のように使える

exchangeString.apply(1);
biExchange.apply(1,2);

springboot devtools のauto restart を疑似高速化する

きっかけ

springbootとintellijなどIDE使ってると、コードの補完はめちゃされるし、Javaって便利だなーとか先人の方たちありがとう!って気持ちでコード書いてるんですけど、コード変更時に変更内容がHotswapで反映されるならいいんですけど、そうじゃないとrestartがかかって、プロジェクトが少し大きくなってくると15秒くらいまたされるのでもっと短縮できないかなーって思いました。

やったこと

DIの対象になるクラスを全部遅延ロード(lazyload)してしまえばいいかと思い、それを実装してみました。
本番環境でやるのはリスキーなので、local環境のみで行うようにしています。

@Profile("local")
@Configuration
public class LazyInitBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        for (String beanName : beanFactory.getBeanDefinitionNames()) {
            beanFactory.getBeanDefinition(beanName).setLazyInit(true);
        }
    }
}

これで15秒から5秒後半くらいになりました!最高

Started WebApplication in 14.565 seconds (JVM running for 16.236)
↓
Started WebApplication in 5.759 seconds (JVM running for 6.871)

リスク

初期化が遅らせているので、初期化順でなにかを行う処理を挟み込んでたりしたら影響がありますが、今日そんなコード書いてる人なんてあんまりいないだろうし、local環境だけなんでまぁ影響ないかなと。

spring-context-indexerと組み合わせているとちょっと動かないケースがあってハマることがあるので、オフにできるならオフにすること。
まだなんでかはわかってないです。

まとめ

これでサクサク開発できるので、しばらく試してみようかと思います