0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Java StreamAPIの頻出メソッドメモ

Last updated at Posted at 2023-07-31

よく使うstream APIのメソッド

例として、以下のDTOクラスがあるとします。

import lombok.Builder;
import lombok.Getter;
import lombok.Setter;

@Setter
@Getter
@Builder
public class SampleDto {

    private String fieldA;
    private boolean fieldB;
    private int fieldC;
}

処理クラスはこんな感じ。

public class Tekito {

    List<SampleDto> dtoList;

    public Tekito(){
        dtoList = new ArrayList<>();
        dtoList.add(SampleDto.builder().fieldA("A1").fieldB(true).fieldC(2).build());
        dtoList.add(SampleDto.builder().fieldA("A2").fieldB(true).fieldC(3).build());
        dtoList.add(SampleDto.builder().fieldA("A3").fieldB(false).fieldC(5).build());
        dtoList.add(SampleDto.builder().fieldA(null).fieldB(true).fieldC(4).build());
        dtoList.add(SampleDto.builder().fieldA("A3").fieldB(false).fieldC(1).build());
    }

    // メソッド
}

フィールドBがすべてtrueであるかのチェック

allMatch()は、与えられた条件にストリームのすべての要素が一致する場合にtrueを返します。

boolean allTrue = dtoList.stream().allMatch(dto -> true == dto.isFieldB());

フィールドBがtrueである要素の個数を取得

long num = dtoList.stream().filter(dto -> true == dto.isFieldB()).count();

フィールドAに3を含む要素が存在するかのチェック

anyMatch()は、与えられた条件にストリームの要素が1つでも一致した場合にtrueを返します。ちなみにallMatchと間違えて使ってしまうことが(私は)多いです。

boolean hasB3 = dtoList.stream().anyMatch(dto -> dto.getFieldA().contains("3"));

フィールドAの値がA4である要素がひとつもなければtrueを取得

noneMatch()は、与えられた条件にストリームの要素が1つも一致しなかった場合にtrueを返します。

boolean falseExistsFlg = dtoList.stream().noneMatch(dto -> "A4".equals(dto.getFieldA()));

フィールドCが最も大きい要素を取得

Optional<SampleDto> maxCElement = dtoList.stream().max(Comparator.comparingInt(SampleDto::getFieldC));

if (maxCElement.isPresent()) {
    SampleDto dto = maxCElement.get();
    System.out.println("FieldA: " + dto.getFieldA() + ", FieldB: " + dto.isFieldB() + ", FieldC: " + dto.getFieldC());
} else {
    System.out.println("リストが空です。");
}

フィールドBの値がfalseである最初の要素を取得

Optional<SampleDto> firstFalseB = dtoList.stream().filter(dto -> false == dto.isFieldB()).findFirst();

if (firstFalseB.isPresent()) {
    SampleDto dto = firstFalseB.get();
    System.out.println("FieldA: " + dto.getFieldA() + ", FieldB: " + dto.isFieldB() + ", FieldC: " + dto.getFieldC());
}else{
    System.out.println("フィールドBがfalseである要素はありません。");
}

フィールドCの値の降順にソート

var sortedList = dtoList.stream()
                        .sorted(Comparator.comparing(SampleDto::getFieldC).reversed())
                        .collect(Collectors.toList());
sortedList.forEach(dto -> System.out.println(dto.getFieldA() + ", " + dto.isFieldB() + ", " + dto.getFieldC()));

フィールドAの値が、他の要素のフィールドAにも存在するかどうかを判定

Map<String, Long> fieldACountMap = dtoList.stream()
    .map(SampleDto::getFieldA)
    .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
boolean hasDuplicate = fieldACountMap.values().stream().anyMatch(count -> count > 1);

フィールドAの値ごとの出現数をMap型変数に格納します。
その上で、anyMatchで判定します。
Stream APIはListに対して使うイメージが強いですが、Mapについても使うことができます。

補足:ラムダ式内のreturnはメソッドを終了するものではない

下記のコードがあるとする。
リストの要素にnullがあれば処理を終了する。
実行すると、「終わり」は出力されない。


    public static void main(String[] args) {
        
        List<String> list = new ArrayList<>();
        list.add("111");
        list.add("222");
        list.add("333");
        list.add(null);
        list.add("444");

        for (String element : list){
            if (element == null){
                return;
            }
        }

        System.out.println("終わり");
    }

これをラムダ式に変えるとこうなる。


    public static void main(String[] args) {
        
        List<String> list = new ArrayList<>();
        list.add("111");
        list.add("222");
        list.add("333");
        list.add(null);
        list.add("444");

        // ラムダ式を使用してnull要素がある場合にreturnする
        list.forEach(element -> {
            if (element == null) {
                return;
            }
        });

        System.out.println("終わり");
    }

しかし、ラムダ式とは無名クラスをさらに簡略化した書き方(厳密には違う模様ではありますが)なので、ラムダ式内のreturnは、そのラムダ式の実行を終了させるだけで、mainメソッドの後続のコードは実行されます。つまり、「終わり」は出力されます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?