業務備忘録

備忘録です

【Java】StreamAPIの練習をする(mapで別のStreamを生成する)

2023-09-06 22:25:30 | 日記

今回は、貸出処理などにかかわらず、ページ数などの書籍の情報を表示するメソッドを作成します。

1.変えたところ

Proc.java

public void showLendInfoAndBookInfo(Map<String, Book> bookMap) {
    Stream<Book> stream = bookMap.values().stream();
           
        //最も貸し出された書籍を表示する。
        System.out.println("最も貸出された書籍のタイトルは『" +
                stream
                .filter(t->t.getLendCount() > 0)
                .sorted((r1,r2)->r2.getLendCount()-r1.getLendCount())
                .map(s->s.getBookName())
                .findFirst()
                .orElse("#Error!!1冊も貸し出されていません!") + "』です。");
       
        //一番ページ数が少ない書籍を表示する。
        System.out.println("図書館で一番ページが少ない本のページ数は" +
                stream.mapToInt(r->r.getPages())
                .sorted()
                .findFirst()
                .getAsInt() + "です。");
    }

 

2つSysoutしているなかでも、上のほうでは、最も貸し出された書籍を表示します。最初にfilter()で貸し出されたことのある書籍に絞り込んだうえで、貸し出し回数でソートします。
map()はStreamを別のStreamで置き換えるメソッドで、これによってStreamがStream(引数のラムダ式内で書籍名=String型を指定)となります。
findFirst()は、Streamの最初のOptionalを返します。Optionalは値がnullである場合の操作を備えたクラスで、orElseは値がnullである場合は、引数に指定した値を返します。
findFirst()で最も貸し出された書籍を取得し、orElse(値が空でない場合は要素を返し、空である場合は引数に指定した要素を返す)で一冊も書籍が貸し出されていない場合の出力を指定しているというわけです。

下の処理ほうの処理では、Bookオブジェクトからページ数で並べ替えてfindFirst()でページ数が最小の書籍のページ数を取得します。

 

『こころ』を2回、『想像の共同体』を1回貸し出しして、実際にshowLendInfoAndBookInfo()を呼び出しましょう。

最も貸出された書籍のタイトルは『こころ』です。

Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed

あれ?

2.そもそもさぁ

StreamはfindFirst()などの終端操作を行うと閉じられてしまい、使いまわしできないようです。一度閉じたStreamを呼び出すとillegalSateExceptionがスローされる。

Stream<Book> stream2 = bookMap.values().stream();
        //一番ページ数が少ない書籍を表示する。
        System.out.println("図書館で一番ページが少ない本のページ数は" +
                stream2
                .mapToInt(r->r.getPages())
                .min()
                .getAsInt()+ "です。");
    }

そもそも「ページ」はint型で管理しているので、わざわざsorted()とかfindFirst()する必要なし。

mapToInt()でIntStream(int型専用のメソッドを備えたクラス)に変換すれば、min()やmax()で最小値/最大値を取得できます。

最も貸出された書籍のタイトルは『こころ』です。

図書館で一番ページが少ない本のページ数は180です。

しかし最大値や最小値、平均などを算出するためにいちいちStreamを作成しなおすのは非常にめんどくさい。

 

IntSummaryStatistics statistics = stream3.map(r->r.getPages()).collect(Collectors.summarizingInt(s->s));

 

System.out.println("図書館で一番長い本のページ数は" + statistics.getMax() + "ページです");

System.out.println("図書館で一番短い本のページ数は" + statistics.getMin() + "ページです");

System.out.println("図書館の本の平均ページ数は" + statistics.getAverage() + "ページです");

System.out.println("図書館の本の冊数は" + statistics.getCount() + "冊です");

IntSummaryStatisticsにcollect(Streamで操作した結果を集約するメソッド)で集約した処理結果を渡すと、最大値や最小値などの情報を保存できます。

図書館で一番ページが少ない本のページ数は180です。

図書館で一番長い本のページ数は530ページです

図書館で一番短い本のページ数は180ページです

図書館の本の平均ページ数は331.25ページです

図書館の本の冊数は8冊です

 

https://gitlab.com/simulacre1/librarytest/-/tree/day1?ref_type=tags