2016-10-14 16 views
1

私の質問は少し複雑です(私は思う)、私は例を使用しようとします。あなたは私の問題を理解するでしょう。私が達成したい何Java 8ストリーム - コレクション内の同じIDを持つオブジェクトの操作

public class User{ 
    private List<Car> cars; 
} 

public class Car{ 
    private String code; 
    private List<Feature> features; 
} 

public class Feature{ 
    private String code; 
} 

ユーザーのリストから、車のリストを取得することですが、私もこれを欲しい:どこ

List<User> users; 

セットの私は、ユーザーのリストを持っていると言います(同じコードを持つ車はない)しかし、私は単一のCarオブジェクトに同じコードを持つ異なる車のすべての機能を持たせ、それが失敗する場所にしたい。今の

私は

List<Car> cars = users 
     .stream() 
     .flatMap(user -> user.getCars()) 
     .??? 

を持っている私は述語を使用してコードで車をフィルタリングすることができます知っているが、私は私を残してのものに機能を追加するために苦しみました。ストリームでそれを行うためのきれいな方法はありますか?

+1

「1台のCarオブジェクトに異なる車のすべての機能を持たせたい」というのは非常に普及している仕様なので、おそらく失敗します。 'Car'オブジェクトが他の車の特徴をどのように持ち、どのような機能について話しているのですか?実生活車と何か関係がありますか? – Holger

+0

あなたは 'distinct()'を使うことができる方法がありますが、 'car.equals(car)'の場合にのみ機能しますが、equalsメソッドはカーコード – Ash

+0

のためにしか機能しないようにする必要があります。コードをフィーチャにマップすること。 'Map >'は、車のリストではありませんが、必要な情報が必要です。 – Ash

答えて

2

すべてのジョイント機能を持つCarをどうやって入手したいのですか?確かに、Userのいずれかの任意のCarインスタンスを変更する必要はありません。したがって、これらの参加をサポートするには、フィーチャリストに参加した後に新しいCarインスタンスを作成する必要があります。

これは以下のように行うことができます。

List<Car> cars = 
    users.stream() 
    .flatMap(user -> user.getCars().stream()) 
    .collect(Collectors.groupingBy(Car::getCode, 
     Collectors.mapping(Car::getFeatures, Collector.of(
      ArrayList<Feature>::new, List::addAll, (a,b)->{a.addAll(b);return a;})))) 
    .entrySet().stream() 
    .map(e -> new Car(e.getKey(), e.getValue())) 
    .collect(Collectors.toList()); 

は、2つのステップがあります。最初のグループは、codeプロパティをキーとしてグループ化操作を実行し、グループ内のすべてCarFeatureのすべてのリストを1つのListに結合します。
これにより、Map<String,List<Feature>>が生成されます。 2番目のステップでは、Car(String code, List<Feature> features)コンストラクタがあると仮定して、各マップエントリを新しいCarインスタンスに変換します。これらの結果CarListに集められます。

上記のコードはすべてFeatureリストを1つのリストに結合することに注意してください。あなたはこれらのリストから重複Feature Sを排除する必要がある場合は、

List<Car> cars = 
    users.stream() 
    .flatMap(user -> user.getCars().stream()) 
    .collect(Collectors.groupingBy(Car::getCode, 
     Collectors.mapping(Car::getFeatures, Collector.of(
      LinkedHashSet<Feature>::new, Set::addAll, (a,b)->{a.addAll(b);return a;})))) 
    .entrySet().stream() 
    .map(e -> new Car(e.getKey(), new ArrayList<>(e.getValue()))) 
    .collect(Collectors.toList()); 

を使用することができます。この最初の重複をなくし、Setに同じcodeCar秒のFeature秒を収集しますが(ケースのために、それは関連性の順序を保持)、Carインスタンスを作成するときにSetListに変換します。

+0

詳細な回答ありがとうございます。私はこの解決法を使って問題に遭遇しました。それはおそらく私の意図をかなり不十分に記述したからでしょう。理想的なソリューションは、予測したように、重複した機能を排除することです。 '型セットはここに適用可能なadd(Object、Object)を定義していません.' ' Object型のaddAll(Object)は未定義です ' 'メソッドsetFeatures (Collection )型のCarは引数(Object)には適用されません ' – qwerty1423

関連する問題