【问题标题】:Filter and Sort internal Map java过滤和排序内部地图java
【发布时间】:2017-09-28 15:10:29
【问题描述】:

我有类人

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

这一切都有效

排序前>

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

我觉得这有点麻烦。我可以简化逻辑吗?

【问题讨论】:

    标签: filter java-8 java-stream


    【解决方案1】:

    给你:

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

    【讨论】:

    • 谢谢。这是最简单的写法。我喜欢 Flatmap 和简单的用法 :)
    【解决方案2】:

    首先,您确定“这一切都有效”吗?我用您的测试数据与以下其他人一起尝试了您的代码:

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

    我不知道您是否认为这“不那么麻烦”,但我希望它有所帮助。

    【讨论】:

    • 谢谢。但我认为这更复杂。我已接受另一位用户的回答。但是谢谢你的时间
    猜你喜欢
    • 2018-02-07
    • 2019-12-30
    • 2019-11-28
    • 1970-01-01
    • 1970-01-01
    • 2021-10-29
    • 2011-11-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多