JavaのEnumをループする方法とabstractメソッドを定義する方法

JavaのEnumをループする方法とabstractメソッドを定義する方法

JavaのEnumをループする方法

JavaのEnumにはvalues()というメソッドがあらかじめ用意されています。

Enumを定義します。lombokのAllArgsConstructorアノテーションはEnumで使用するとprivateコンストラクタになります。

package jp.co.confrage;

import lombok.AllArgsConstructor;
import lombok.Getter;

@AllArgsConstructor
@Getter
public enum Sample {
  APPLE("1"),
  ORANGE("2"),
  BANANA("3");

  private String param;
}

このEnumをループしたい場合は以下のようにコーディングします。

for (Sample a: Sample.values()) {
  System.out.println(a.getParam());
}

結果は以下のようになります。

1
2
3

ストリームを使用してもループは可能です。

Arrays.stream(Sample.values()).forEach(r -> {
  System.out.println(r.getParam());
});

結果は以下のようになります。

1
2
3

Arrays.asListを使用してからストリームにしてmapで値だけとってきてループとかもできます。

Arrays.asList(Sample.values()).stream().map(Sample::getParam).collect(Collectors.toList()).forEach(r -> {
  System.out.println(r);
}); // 注

結果は以下のようになります。

1
2
3

findAny().isPresent()で値が存在するかどうかを判断します。

Boolean flag = Arrays.stream(Sample.values()).filter(r -> r.getParam().equals("3")).findAny().isPresent();

filter()でフィルタリングしてfindAny()で要素を返してisPresent()で存在確認することができます。

存在すればtrue,存在しなければfalseです。

JavaのEnumでAbstractメソッドを定義する方法

EnumでAbstractメソッドを定義して実行する方法があります。抽象メソッドを定義した場合、各列挙子にその実装メソッドを定義する必要があります。

public enum Sample {
  APPLE{
    public String getStr(String str) { // 定義
      return "test" + str;
    }
  };
  public abstract String getStr(String str); // ここで抽象メソッドを定義する
}

これを実際に使うにはEnum型で受けます。

public static void main(String args[]){
  Sample a = Sample.APPLE;
  String ret = a.getStr("aiueo");
  System.out.println(ret); // testaiueoと表示される
}

valueOfメソッド

EnumではstaticメソッドとしてvalueOfメソッドが用意されています。StringからEnumへ変換します。Enum値が存在しない文字列を指定した場合は、IllegalArgumentExceptionエクセプションが発生します。

以下、例です。

package jp.co.confrage;

public class EnumTtest {
  public enum Answer {
    OK,
    NG
  }

  public static void main(String[] args) {
    Answer answer = Answer.valueOf("OK");
    System.out.println(answer.toString()); // OKと表示される
    System.out.println(Answer.valueOf("NG")); // NGと表示される
    System.out.println(Answer.valueOf("NGxxx")); // IllegalArgumentException
  }
}

ordinalメソッド

ordinalメソッドを使用すると、Enumの宣言順を取得することが可能です。基底値は0となります。

package jp.co.confrage;

public class EnumTtest {
  public enum Answer {
    OK,
    NG
  }

  public static void main(String[] args) {
    System.out.println(Answer.OK.ordinal()); // 0と表示される
    System.out.println(Answer.NG.ordinal()); // 1と表示される
  }
}

メンバ変数定義

JavaのEnumではメンバ変数を定義することができます。

メンバ変数は定数となるのでfinalを付けます。

コンストラクタはpublicだとエラーとなり、privateコンストラクタを定義して初期化します。

以下例です。

public enum Answer {
  OK(1),
  NG(0);

  private final int answer; // メンバ変数にはfinalをつけること、つけなくてもエラーにはならない

  // プライベートな引数ありコンストラクタ
  private Answer(final int answer) { // 定数なのでfinalにする
    this.answer = answer;
  };
        
  // getter
  public int getAnswer() {
    return this.answer;
  }
}

// 実行する
public class EnumTtest {    
  public static void main(String[] args) {
    System.out.println(Answer.OK.getAnswer()); // 1と表示される
    System.out.println(Answer.NG.getAnswer()); // 0と表示される
  }
}

これをlombokのアノテーションを使用すると以下のようにボイラープレートコードを省略できます。

public class EnumTtest {
  public static void main(String[] args) {
    System.out.println(Answer.OK.getAnswer()); // 1と表示される
    System.out.println(Answer.NG.getAnswer()); // 0と表示される
  }
}

@Getter
@RequierdAllArgsConstructor
public enum Answer {
  OK(1),
  NG(0);        
  private final int answer; // メンバ変数にはfinalをつけること、つけなくてもエラーにはならない
}

EnumをMapクラスで変換

既存システムのjarファイル内に存在するEnumを使用しつつ、新規システムで流用したい。でも少し列挙子の名前が異なる、といった場合にif文で分岐しました。

既存システムのEnum

package jp.co.confrage;

import lombok.AllArgsConstructor;
import lombok.Getter;

@AllArgsConstructor
@Getter
public enum Enum {
  Saturday("土"),
  Sunday("日");
  private String day;
}

新規システムでは、土→土曜、日→日曜としたいとします。(実際の列挙子はもっと多い)

既存システムのjarは修正が出来ない状態でした。if文で書く方法があります。

private String getXxx(String day) {
  String ret = null;
  if (Objects.equals(Enum.Saturday.name(), day)) { // "Saturday"
    ret = "土曜";
  } else if (Objects.equals(Enum.Sunday.name(), day)) { // "Sunday"
    ret = "日曜";
  }
  return ret;
}

これだと循環的複雑度が上がってしまう為、Mapクラスを作成し、変換してみました。

private String getXxx(String day) {
  Map<String, String> replaceMap =
    new LinkedHashMap<>() {
      {
        put(Enum.Saturday.name(), "土曜");
        put(Enum.Sunday.name(), "日曜");
      }
    };
  String ret = replaceMap.get(day)); // "Saturday" or "Sunday"
  return ret;
}

Java1.5より追加されたEnumMapクラスを使って変換する例です。

private String getXxx(Enum day) {
  final EnumMap<Enum, String> map = new EnumMap<>(Enum.class);
  map.put(Enum.Saturday, "土曜");
  map.put(Enum.Sunday, "日曜");
  return map.get(day); // 土曜 or 日曜
}

注:Java16から以下メソッド追加されました。

.collect(Collectors.toList());

.toList();

コメント

タイトルとURLをコピーしました