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?

StreamAPIを使用したコレクションの処理について学んだこと

Posted at

目的:学習したことの整理・アウトプット

 
今回扱うクラスの処理の目的:Readerメソッドで取得した情報をユーザーごとに分けて請求額を計算(Readerで得た情報の処理)

流れ
ユーザーごとに(UserIdで)に請求情報をまとめて管理
   ⇩
全部の請求(finalPaymentAmount)をリストから取り出す
   ⇩
支払方法に応じて、請求金額の合計を計算
   ⇩
請求額の合計をアウトプット(Writerメソッドへ)

ItemProcessorの処理全体

※個別の処理の解説は下へ

ItemProcessor.java
@Bean
public ItemProcessor<List<BillingRecord>, List<UserTotalBilledAmount>> processor() {
    return billingRecords -> {
        // ユーザーごとに請求記録をグループ化
        Map<Integer, List<BillingRecord>> groupedByUser = billingRecords.stream()
            .collect(Collectors.groupingBy(BillingRecord::getUserId));

        // 結果リストの準備
        List<UserTotalBilledAmount> results = new ArrayList<>();

        // グループごとに処理
        for (Map.Entry<Integer, List<BillingRecord>> entry : groupedByUser.entrySet()) {
            // ユーザー情報の取得
            int userId = entry.getKey();
            String userName = entry.getValue().get(0).getUserName();
            String creditCardNumber = entry.getValue().get(0).getCreditCardNumber();

            // 請求金額の合計を計算
            double totalAmount = 0.0;
            for (BillingRecord record : entry.getValue()) {
                double amount = record.getFinalPaymentAmount();
                switch (record.getPaymentId()) {
                    case 1:
                        totalAmount += amount;      // 全額加算
                        break;
                    case 6:
                        totalAmount += amount / 6;  // 6分の1を加算
                        break;
                    case 12:
                        totalAmount += amount / 12; // 12分の1を加算
                        break;
                    default:
                        totalAmount += 0;           // 何もしない
                        break;
                }
            }

            // 結果オブジェクトを作成してリストに追加
            UserTotalBilledAmount userTotal = new UserTotalBilledAmount(userId, userName, creditCardNumber, totalAmount);
            results.add(userTotal);
        }

        // 結果を返却
        return results;
    };
}

やりたいこと(目的)と手段

目的1
ユーザーごとに請求情報一覧をまとめたい。
  ⇩ 言い換えると、、
ユーザーIdとその請求額をセットでまとめたい。

Map<Integer, List<BillingRecord>> groupedByUser = billingRecords.stream()
            .collect(Collectors.groupingBy(BillingRecord::getUserId));

 
手段(抽象度_高)
1. Mapで管理する
2. コレクションの種類を変換する
※処理順番は2.=>1.

手段(具体度_高)

  1. **.stream()**を使用してコレクション生成
  2. コレクションに対して、groupingByメソッドカテゴリー分け&ユーザーIdと請求情報の紐づけ

 
参考
Stream APIの基本
groupingByメソッドの使い方
ラムダ式の使い方

 
目的2
マップからキーと値を取りだし、ユーザーId、ユーザー名、クレジットカード番号、当該月の請求額合計セットで管理したい。

List<UserTotalBilledAmount> results = new ArrayList<>();

for (Map.Entry<Integer, List<BillingRecord>> entry : groupedByUser.entrySet()) {
            
            int userId = entry.getKey();
            String userName = entry.getValue().get(0).getUserName();
            String creditCardNumber = entry.getValue().get(0).getCreditCardNumber();

            (中略) 
            
            UserTotalBilledAmount userTotal = new UserTotalBilledAmount(userId, userName, creditCardNumber, totalAmount);
            results.add(userTotal);
        }

        return results;

手段(抽象度_高)

  1. 上記4項目を保持するオブジェクトを格納するためのリストを用意
  2. Mapから4項目を取得
    マップに含まれるキーと値のマッピングのセットを取得する
  3. 請求額合計を支払い方法に応じて合計・計算(中略部分)
  4. 「1.」で作成したリストへ格納
  5. 「4.」のリストを出力

 
手段(具体度_高)

  1. Mapから4項目を取得
    entrySet()メソッドと拡張forを利用してキーと値のセットを取得する
    Ⅰ.ユーザーId = キーなので getKey()メソッドで取得
    Ⅱ.ユーザー名とクレジットカード番号は、 getValue().get(0).getフィールド名()メソッドで取得
    ※ユーザーIdでグループ化した請求情報リスト内のユーザー名とクレカ番号は、同じユーザーに属するため、get(0)でリストの先頭を指定すればよい
  2. 省略
  3. インスタンス化&フィールド変数をセット
  4. addメソッドでリストへ追加

 
参考
拡張for文を利用したMapのキーと値の取得
Mapで使用する主要メソッド
Iteratorとは

 
目的3
支払方法に応じて当月の請求を計算する。(1,6,12回払いの3種類)

 switch (record.getPaymentId()) {
                    case 1:
                        totalAmount += amount;      // 全額加算
                        break;
                    case 6:
                        totalAmount += amount / 6;  // 6分の1を加算
                        break;
                    case 12:
                        totalAmount += amount / 12; // 12分の1を加算
                        break;
                    default:
                        totalAmount += 0;           // 何もしない
                        break;
                }

特定のデータの値パターンをチェックしたい場合は「switch文」を使う。
基本は条件分岐はIf文で対応すべきだが、場合によってはswitch文の方が可読性が高くなる

 

参考

https://java-code.jp/1501
https://enterprisegeeks.hatenablog.com/entry/2014/06/19/093000#:~:text=partitioningBy%2C%20groupingBy,%22%20%3D%20%22%20%2B%20v%3B
https://en-ambi.com/itcontents/entry/2019/04/25/103000/#%E3%83%A9%E3%83%A0%E3%83%80%E5%BC%8F%E3%81%AE%E5%9F%BA%E6%9C%AC:~:text=%E3%81%84%E3%82%8B%E3%81%A7%E3%81%97%E3%82%87%E3%81%86%E3%80%82-,List%3CInteger%3E%20numbers%20%3D%20List.of(3%2C%201%2C%20%2D4%2C%201%2C%20%2D5%2C%209%2C%20%2D2%2C%206%2C%205%2C%203%2C%205)%3B%0Anumbers.stream()%0A%20%20%20%20%20%20%20%20.filter(number%20%2D%3E%20Math.abs(number)%20%3E%3D%205)%0A%20%20%20%20%20%20%20%20.forEach(System.out%3A%3Aprintln)%3B,-%E5%BC%95%E6%95%B0%E3%81%AE%E5%80%A4
https://www.techiedelight.com/ja/iterate-map-in-java-using-entryset/#google_vignette
https://dtnavi.tcdigital.jp/cat_web/web_015/
https://workteria.forward-soft.co.jp/blog/detail/10082

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?