java8 删除空元素后制作不可变列表

java8 make immutable List after removing null elements

我知道 Arrays.asList 创建不可变的 List。我的要求是创建不可变的 List<Student>,其中没有 null 元素。所以我首先创建 new ArrayList() 然后使用 java 8 filters 删除 null 元素,如下所示:

List<Student> list = new ArrayList<>();
list.add(makeStudent("ram", 'M'));
list.add(makeStudent("sathya", 'F'));
list.add(makeStudent(null, 'M'));
list.add(makeStudent("sri", 'M'));

list = list.stream().filter(s -> s != null).collect(Collectors.toList());

下面是 makeStudent 方法,returns null 如果名称不可用:

private Student makeStudent(String name, char gender) {
    return null != name ? new Student(name, gender) : null;
}

我以为 Collectors.toList() 会创建不可变的。但是我错了。 list 在这里仍然是可变的。有没有更好的方法使 list 干净(删除 null)并且使用 java 8 在单行中不可变?

使用 Collections.unmodifiableList 包装流收集的 List

list = Collections.unmodifiableList(list.stream()
                                        .filter(Objects::nonNull)
                                        .collect(Collectors.toList()));

Collectors.toList() 方法执行类似 reduce 的操作:

//pseudo-code
Collectors.reduce(ArrayList::new, List::add, List::addAll)

IF 你传递了一个不可变的 List 来减少你不能从流中收集任何项目到 List 因为它是不可变的。

您可以按照其他答案中的建议使用 Collections.unmodifiableList,也可以将流转换为数组,然后使用 Arrays.asList

list = Arrays.asList(list.stream()
                         .filter(Objects::nonNull)
                         .toArray(Student[]::new));

您可以将您的代码重写为以下代码:

list = list.stream()
           .filter(Objects::nonNull)
           .collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));

收集器collectingAndThen 允许您包装结果集合

即使您指定了 Java 8,以下是如何将现有的 List 过滤为完全 immutable List '正在寻找 Java 9:

list = list.stream()
           .filter(Objects::nonNull)
           .collect(Collectors.toCollection(List::of));