Javaのストリームを使用して、子オブジェクトをドメインオブジェクトにフラットなリストを変換します

アダム:

私は、JDBCの結果セットからインスタンスフラットデ正規化構造の着信オブジェクトを持っています。入ってくるオブジェクトは、私は、ネストされた子のコレクションを持つ親オブジェクトのリストにデータを変換するので、つまりオブジェクトグラフ、または正規化されたリスト、繰り返しデータのロードがあります、結果セットを反映しています。

入ってくるオブジェクトのクラスは、次のようになります。

class IncomingFlatItem {
    String clientCode;
    String clientName;
    String emailAddress;
    boolean emailHtml;
    String reportCode;
    String reportLanguage;
}

私は1つのクライアントのクライアントのための電子メールアドレスオブジェクトのリストを含むオブジェクト、およびレポートオブジェクトのリストに集約したいのですが、各クライアントのために複数のオブジェクトが含まれて入ってくるデータはそう。

だから、Clientオブジェクトは、次のようになります。

class Client {
    String clientCode;
    String clientName;
    Set<EmailAddress> emailAddresses;
    Set<Report> reports;
}

不思議なことに、私は、このために、既存の答えを見つけることができません。私は、ストリームをネストまたはストリームをチェーンで探していますが、私は最もエレガントなアプローチを見つけるしたいと私は間違いなくforループを回避したいです。

アダム:

言及したすべての回答者に感謝Collectors.groupingBy()これは私が使用できるストリームを設定するための鍵でしたreduce()私は誤って私が使用することができるはずと信じていたreduceずに、問題を解決するために自分自身でgroupingBy

また、流暢なAPIを作成するための提案に感謝します。私が追加IncomingFlatItem.getEmailAddress()IncomingFlatItem.getReport()流暢にからドメインオブジェクトをつかむIncomingFlatItem-ともすでにネストされたその電子メールやレポートとの適切なドメインオブジェクトに全体の平らなアイテムを変換する方法:

public Client getClient() {
    Client client = new Client();
    client.setClientCode(clientCode);
    client.setClientName(clientName);
    client.setEmailAddresses(new ArrayList());
    client.getEmailAddresses().add(this.getEmailAddress());
    client.setReports(new ArrayList<>());
    client.getReports().add(this.getReport());
    return client;
}

私はまた、作成されたビジネスIDをベース.equals().hashCode()上の方法ClientEmailAddressおよびReport@SamuelPhilipによって推奨されているように

最後にドメインオブジェクトのために、私が作成.addReport(Report r)し、.addEmail(EmailAddress e)私の上Clientに子オブジェクトを追加し、クラス、Client既に存在している場合ではありません。私は不時着Setのためのコレクション型をListドメインモデルの標準であるためListSetsへの変換の多くを意味しているだろうLists

だからと、ストリームコードとラムダは簡潔に見えます。

3つのステップがあります。

  1. マップIncomingFlatItemsClients
  2. グループClients(に大きく依存クライアントによるマップへClient.equals()
  3. 1に、各グループを減らします Client

だから、これは機能的なアルゴリズムは次のとおりです。

List<Client> unflatten(List<IncomingFlatItem> flatItems) {
    return flatItems.parallelStream()
            .map(IncomingFlatItem::getClient)
            .collect(Collectors.groupingByConcurrent(client -> client))
            .entrySet().parallelStream()
            .map(kvp -> kvp.getValue()
                    .stream()
                    .reduce(new Client(), 
                            (client1, client2) -> {
                                    client1.getReports()
                                            .forEach(client2::addReport);
                                    client1.getEmailAddresses()
                                            .forEach(client2::addEmail);
                                    return client2;
                    }))
            .collect(Collectors.toList());
}

私は本当に理解する前に私が原因接線にオフに行くまでに長い時間がかかったreduce-私が使用している間私のテストに合格した解決策を見つけた.stream()が、完全に失敗し.parallelStream()、ここで、したがって、その使用。私が使用していたCopyOnWriteArrayListとしても、それ以外の場合は、ランダムに倒れるでしょうConcurrentModificationExceptions

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=226555&siteId=1