2017-09-28 10 views
1

は、私はあなたが名前と年齢を無視することができますフィルタとソート内部地図のJava

private String name; 
    private int age; 
    private Map<String, LocalDate> carsBoughWithDate; 

クラスPersonを持っています。

[Person{name='John', age=22, carsBoughWithDate={Toyota=2017-02-01, Corolla=2017-02-01}}, 

Person{name='Michael', age=44, carsBoughWithDate={Vauxhall=2017-01-01, Toyota=2017-01-01, BMW=2017-01-01}}] 

:ここで重要なのは原因私は人の車を保存していますいくつかの理由にcarsBoughWithDate

は日付

テストデータ

Map<String, LocalDate> carsbought = new HashMap<>(); 
     carsbought.put("Toyota", LocalDate.of(2017, 2, 1)); 
     carsbought.put("Corolla", LocalDate.of(2017, 2, 1)); 

     Person john = new Person("John", 22, carsbought); 


     carsbought = new HashMap<>(); 
     carsbought.put("Vauxhall", LocalDate.of(2017, 1, 1)); 
     carsbought.put("BMW", LocalDate.of(2017, 1, 1)); 
     carsbought.put("Toyota", LocalDate.of(2017, 1, 1)); 

     Person michael = new Person("Michael", 44, carsbought); 

     List<Person> personList = new ArrayList<>(); 
     personList.add(john); 
     personList.add(michael); 

出力にマップに枝であります今、私は車を買った人を見つけなければならないが、その車を購入した人をリストの一番上に並べる

例:車を持っている検索者は "トヨタ" やBMW

これは私が

**

System.out.println("Before sort >" + personList); 
     List<Person> sortedList = Lists.newArrayList(); 
     HashMap<LocalDate, Person> collect = Maps.newHashMap(); 
     for (Person person : personList) { 
      Map<String, LocalDate> docCarsBoughWithDate = person.getCarsBoughWithDate(); 
      collect.putAll(docCarsBoughWithDate.entrySet().stream() 
        .filter(map -> Lists.newArrayList("Toyota", "BMW").contains(map.getKey())) 
        .collect(HashMap::new, 
          (m, v) -> m.put(
            v.getValue(), 
            person), 
          HashMap::putAll 
        )); 
     } 
     Map<String, List<Person>> collect1 = collect.entrySet().stream().sorted(Map.Entry.comparingByKey()).map(m -> m.getValue()).collect(Collectors.groupingBy(Person::getName)); 
     collect1.keySet().forEach(key -> sortedList.add(collect1.get(key).get(0))); 
     System.out.println("after sort > " + sortedList 
     ); 

このすべてが前に

の作品をやっていることですソート>

[Person{name='John', age=22, carsBoughWithDate={Toyota=2017-02-01, Corolla=2017-02-01}}, Person{name='Michael', age=44, carsBoughWithDate={Vauxhall=2017-01-01, Toyota=2017-01-01, BMW=2017-01-01}}] 

ソート>

[Person{name='Michael', age=44, carsBoughWithDate={Vauxhall=2017-01-01, Toyota=2017-01-01, BMW=2017-01-01}}, Person{name='John', age=22, carsBoughWithDate={Toyota=2017-02-01, Corolla=2017-02-01}}] 

後、私はこれは少し面倒であると感じています。論理を単純化することはできますか?

答えて

2

あなたが行く:

List<Person> sortedList = personList.stream() // 
     .flatMap(p -> p.getCarsBoughWithDate().entrySet().stream() // 
       .filter(e -> targetCarNames.contains(e.getKey())) // filter the bought cars which are in the target bought cars. 
       .sorted(Entry.comparingByValue()).limit(1) // sorted and only fetch the entry with earliest bought date. 
       .map(e -> new SimpleEntry<>(p, e.getValue()))) // composite a new entry with the person and the earliest bought date. 
     .sorted(Entry.comparingByValue()).map(e -> e.getKey()).collect(toList()); // 
+0

ありがとう。これが書ける最も簡単な方法です。私はフラットマップとシンプルトリーの使用が好きです:) – Makky

1

まず、「これはすべて動作する」ことを確認してください。私は、次の追加の人とあなたのテストデータを使用してコードを試してみました:

carsbought = new HashMap<>(); 
carsbought.put("BMW", LocalDate.of(2017, 2, 1)); 
Person sally = new Person("Sally", 25, carsbought); 

と彼女は同じ日に車を買ったことが起こったので、彼女はジョンを上書きしました。

第2に、複雑な問題を解決する戦略は、単純な問題に分解することです。

private Optional<LocalDate> firstDateOf(Person person, Collection<String> cars) 
{ 
    return person.getCarsBoughWithDate().entrySet().stream() 
     .filter(e -> cars.contains(e.getKey())) 
     .map(Map.Entry::getValue) 
     .min(Comparator.naturalOrder()); 
} 

これは人々のソート・キーになります。例えば、私は最初の人が車のセットの1つを買った時に最初の日付を決定する方法を追加します。そして、ソートキーに一人一人をマッピングするために、このメソッドを使用し、最終的にリストを並べ替え:あなたは、この「あまり面倒」を検討している場合

List<Person> sortCarOwners(Collection<Person> people, Collection<String> cars) 
{ 
    Map<Person, Optional<LocalDate>> personToDateMap = people.stream() 
     .collect(Collectors.toMap(p -> p, p -> firstDateOf(p, cars))); 
    return personToDateMap.entrySet().stream() 
     .filter(e -> e.getValue().isPresent()) 
     .sorted(Comparator.comparing(e -> e.getValue().get())) 
     .map(e -> e.getKey()) 
     .collect(Collectors.toList()); 
} 

私は知らないが、私はそれが役に立てば幸い。ここで

+0

感謝を。しかし、私はこれがもっと複​​雑だと思います。私は別のユーザーからの回答を受け入れました。しかし、あなたのおかげで時間が – Makky