有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

用于空键的java流groupBy收集器和分组值列表上的应用收集器

我有以下的班级定义-

    class Employee {

                Long key;
                String initials;
                Integer age;
    }

下面是IntWrapper类的定义-

    class  IntWrapper {
            private Integer i;
    }

我在一个列表List<Employee> = ...中收集了员工对象

现在我想创建一个Map<String, Integer>,其中key是初始值,value是具有该初始值的员工的最大年龄

我通过以下逻辑实现了这一点-

    Map<String, IntWrapper> r2 = empList.stream().collect(Collectors.groupingBy(e -> e.getName(),
                    Collectors.collectingAndThen(Collectors.maxBy(Comparator.nullsLast(Comparator.comparingInt(Employee::getAge))), empOpt -> empOpt.map(x -> new IntWrapper(x.getAge())).orElseGet(() -> null) )));

如果没有姓名首字母为空的员工,这里的一切都正常。如果存在,则抛出NullPointerException

我在这个SO posthttps://stackoverflow.com/a/22650233/2541276中找到了一个使用空键的groupby解决方案

    public static <T, A> Collector<T, ?, Map<A, List<T>>>
        groupingBy_WithNullKeys(Function<? super T, ? extends A> classifier) {
            return Collectors.toMap(
                    classifier,
                    Collections::singletonList,
                    (List<T> oldList, List<T> newEl) -> {
                        List<T> newList = new ArrayList<>(oldList.size() + 1);
                        newList.addAll(oldList);
                        newList.addAll(newEl);
                        return newList;
                    });
        }

现在我不知道如何在结果值上应用收集器,因为Collectors.toMap不会在结果类型上应用收集器

有什么帮助吗?我怎样才能达到同样的效果


共 (1) 个答案

  1. # 1 楼答案

    如果要忽略首字母为空的员工,可以过滤空initials,然后收集为映射

    Map<String, IntWrapper> result = empList.stream().filter(e -> e.getInitials() != null)
        .collect(Collectors.toMap(e -> e.getInitials(), x -> new IntWrapper(x.getAge()),
            BinaryOperator.maxBy(Comparator.comparing(IntWrapper::getI))));
    

    或者使用Optional作为映射键,将空首字母用作键

    Map<Optional<String>, IntWrapper> result = empList.stream().filter(e -> e.getInitials() != null)
            .collect(Collectors.toMap(e -> Optional.ofNullable(e.getInitials()), x -> new IntWrapper(x.getAge()),
                BinaryOperator.maxBy(Comparator.comparing(IntWrapper::getI))));