Javaのパターンメモ

個人的なメモなので、雑に適当に追加されていくかもしれないし放置されるかもしれない

## Arrays.asListよりもList.of
JDK9以降では、`Arrays.asList`よりも`List.of`を使うほうがいいです。
`Arrays.asList`が返す`List`は単に配列のラッパで、サイズ固定だけど要素の変更が可能です。一方、`List.of`が返す`List`は要素の変更もできずimmutableになります。

## n -> new int[n]はint[]::new
これ、なかなか謎構文に見えるけど、そういうもんです。
`new String(data)`が`String::new`と書けるのと同じで。

## FunctionalInterfaceのフィールドを使わない

```java
final Function<String, Price> CONVERT_STRING_TO_PRICE = 
  str -> str.substring(0, str.length() - 1).transfer(Price::of);
```
というフィールドを定義して

```java
return inputs.stream()
  .map(CONVERT_STRING_TO_PRICE)
  .collect(toList());
```
のように使うことがあります。

けどこれは、普通にメソッドを定義して、

```java
Price stringToPrice(String str) {
  return str.substring(0, str.length() - 1).transfer(Price::of);
}
```
メソッド参照を使うほうがいいです。

```java
return inputs.stream()
  .map(Converters::stringToPrice)
  .collect(toList());
```

JavaDocでのコメントも適切に書けるし、高階関数よりもメソッドのほうが読みやすいです。
また、結局ラムダはメソッド定義とメソッド参照にコンパイルされるので、ちょっと無駄になります。

## Optionalをフィールドに使わない
`Serializable`ではないなどあるので、`@Nullable`などをつけて普通の値を使うほうがいいです。

## Streamを戻り値に使わない
Stream自体を操作するメソッドじゃない限りはStreamを戻り値にしないほうがいいです。
基準としては`Stream<T>`は返していいけど、`Stream<String>`など具体的な型を返すものはあまりよくない
もしくはFiles.linesのように、I/Oが入って「ストリーム処理」をしたい場合など。

## Streamパターン

### boolean[]やchar[]をStream処理したいときはIntStreamを使う

たとえばcharsがあるとして。

```java
char[] chars;
```

Arrays.streamにはchar[]を受け取るものがないのでエラ―です。
Stream.ofを使うとchar配列自体を扱うStreamができます。
なので、IntStreamを使ってインデックスを生成しつつmapToObjectします。

```java
IntStream.range(0, chars.length)->mapToObject(i -> chars[i])
```

### int配列ビルダーが欲しいときはIntStream.builder()を使う

```java
var builder = IntStream.builder();
builder.add(2);
builder.add(5);
int[] result = builder.build().toArray();
```

### anyMatch

```java
for (var a : list) {
  if (condition(a)) {
    return true;
  }
}
return false
```
↓

```java
return list.stream().anyMatch(this::condition);
```
### allMatch

```java
for (var a : list) {
  if (!condition(a)) {
    return false;
  }
}
return true
```
↓

```java
return list.stream().allMatch(this::condition);
```


### noneMatch


```java
for (var a : list) {
  if (condition(a)) {
    return false;
  }
}
return true
```
↓

```java
return list.stream().noneMatch(this::condition);
```


## OptionalにStreamやListをいれない
`Optional`は要素0か1の特殊なコレクションなので、StreamやListをさらに囲む必要はなくStream.of()やemptyList()で対応できるはず

## if

### 正常系と異常系

thenに正常系、elseに異常系を

```java
if (cond) {
  proc
} else {
  error
}
```
ただし異常系が1行でreturn/throwするときは異常系をifに入れて早期脱出を。

```java
if (!cond) {
  throw error
}
proc
```

### !(aa && bb)

`!(aa && bb)`のように大きくカッコでくくって反転は避けたほうがよさげ

```java
if (!(hasValue && isValid)) {
  error
}
```
よりは

```java
if (!hasValue || !isValid) {
  error
}
```
のほうが、結果を脳にキャッシュしなくていい。
ただし、`else`がつくなら

```java
if (!hasValue || !isValid) {
  error
} else {
  proc
}
```
よりは

```java
if (hasValue && isValid) {
  proc
} else {
  error
}
```
のほうが反転がなくてよい。
この場合は正常系をthenにという方針にも従ってる。
あと、こういった論理の反転はIDEがやってくれるはずなので手でやらないほうが吉。

## enum

パラメータをもつときにはlombokの`@AllArgsConstructor`と`@Getter`をつける。
`@Value`は`enum`に使えない。

```java
@AllArgsConstructor
@Getter
enum Hoge {
  A("a-desu"),
  B("b-dayo");

  private String message;
}
```

## Integer.valueOfはIntegerを返す
`Integer`や`Long`の`valueOf`はラッパーオブジェクトを返す。
なのでこのようなコードは無駄がある

```java
int n = Integer.valueOf(str);
```

プリミティブとして使いたい場合は`parseInt`を使う

```java
int n = Integer.parseInt(str);
```

## IOExceptionを非検査例外にするにはUncheckedIOExceptionを使う

```java
catch (IOException ex) {
  throw new UncheckedIOException(ex);
}
```

## テストのためにpackage privateを使うときはVisibleForTestingをつける
Guavaの`@VisibleForTesting`をつけます。JUnitで持ってほしいですね。

```java
@VisibleForTesting
String createId(String seed) {
}
```