2017-09-28 2 views
1

I ont la classe Personneet options de recherche interne Carte java

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

Vous pouvez ignorer le nom et l'âge. L'importante ici est carsBoughWithDate

pour une raison quelconque je sauve les voitures personne bough dans une carte avec la date

données de test

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); 

Sortie:

[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}}] 

Maintenant, je dois trouver la personne qui a acheté des voitures, mais ensuite trier la personne qui a acheté la voiture le plus tôt dans la liste.

Exemple: recherche personne qui a des voitures "Toyota" ou BMW

C'est ce que je l'ai fait

**

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 
     ); 

Tout cela fonctionne

Avant sort>

[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}}] 

après tri>

[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}}] 

Je pense que c'est peu encombrant. Puis-je simplifier la logique?

Répondre

2

Ici, vous allez:

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

Merci. C'est la manière la plus simple de l'écrire. J'aime l'utilisation de Flatmap et de la simpletry :) – Makky

1

Tout d'abord, êtes-vous sûr que "tout cela fonctionne"? J'ai essayé votre code avec vos données de test avec la personne supplémentaire suivante:

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

et elle écrasait John parce qu'elle est arrivé à avoir acheté une voiture à la même date. Deuxièmement, la stratégie pour résoudre des problèmes complexes consiste à les décomposer en problèmes plus simples. Par exemple, je voudrais tout d'abord ajouter une méthode qui détermine la première date à laquelle une personne a acheté un d'un ensemble de voitures:

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()); 
} 

Ce sera la clé de tri du peuple. Ensuite, utilisez cette méthode pour associer chaque personne à la clé de tri et enfin trier la liste:

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()); 
} 

Je ne sais pas si vous considérez cette « moins lourde », mais j'espère que cela aide.

+0

Merci. Mais je pense que c'est plus complexe. J'ai accepté la réponse d'un autre utilisateur. Mais merci pour le temps – Makky