过滤和排序内部Map java

时间:2017-09-28 15:10:29

标签: filter java-8 java-stream

我有班级人员

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

您可以忽略姓名和年龄。这里重要的是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);

输出:

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

现在,我必须找出购买汽车的人,然后将最早购买汽车的人排在列表顶部

示例:搜索拥有“丰田”或“宝马”汽车的人

这就是我所做的

**

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

这一切都有效

排序&gt;

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

排序&gt;

[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 个答案:

答案 0 :(得分: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()); //

答案 1 :(得分:1)

首先,你确定&#34;这一切都有效吗?#34;?我和下面的其他人一起用你的测试数据尝试了你的代码:

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

她覆盖了约翰,因为她碰巧在同一天买了一辆汽车。

其次,解决复杂问题的策略是将其分解为更简单的问题。例如,我首先会添加一个方法来确定一个人购买一组汽车中的一个的第一个日期:

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

这将成为人们的排序关键。然后使用此方法将每个人映射到排序键,最后对列表进行排序:

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

我不知道你是否认为这不那么麻烦&#34;但我希望它有所帮助。