MST

星途 面试题库

面试题:Java Stream API自定义Collector的深度应用

设计一个自定义Collector,用于将一个包含字符串的Stream按照单词长度进行分组,每个组内的字符串按字典序排序,最终返回一个Map,键为单词长度,值为排序后的字符串List。请详细说明实现思路和关键代码。
30.4万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

实现思路

  1. 创建一个自定义的 Collector,该 Collector 需要定义如何将流中的元素收集到一个中间数据结构中,以及如何将中间数据结构合并(在并行流的情况下),并最终生成所需的 Map
  2. 使用 HashMap 作为中间数据结构,键为单词长度,值为 List<String>
  3. 对于流中的每个字符串,计算其长度并将其添加到对应的 List 中。
  4. 最后,对每个 List 进行字典序排序。

关键代码

import java.util.*;
import java.util.stream.Collector;
import java.util.stream.Collectors;

public class WordLengthGroupingCollector implements Collector<String, Map<Integer, List<String>>, Map<Integer, List<String>>> {

    @Override
    public Supplier<Map<Integer, List<String>>> supplier() {
        return HashMap::new;
    }

    @Override
    public BiConsumer<Map<Integer, List<String>>, String> accumulator() {
        return (map, word) -> {
            int length = word.length();
            map.computeIfAbsent(length, k -> new ArrayList<>()).add(word);
        };
    }

    @Override
    public BinaryOperator<Map<Integer, List<String>>> combiner() {
        return (map1, map2) -> {
            map2.forEach((length, words) -> map1.computeIfAbsent(length, k -> new ArrayList<>()).addAll(words));
            return map1;
        };
    }

    @Override
    public Function<Map<Integer, List<String>>, Map<Integer, List<String>>> finisher() {
        return map -> {
            map.values().forEach(Collections::sort);
            return map;
        };
    }

    @Override
    public Set<Characteristics> characteristics() {
        return Collections.unmodifiableSet(EnumSet.of(Characteristics.IDENTITY_FINISH, Characteristics.CONCURRENT));
    }

    public static void main(String[] args) {
        List<String> words = Arrays.asList("apple", "banana", "cherry", "date", "fig", "grape");
        Map<Integer, List<String>> result = words.stream().collect(new WordLengthGroupingCollector());
        result.forEach((length, sortedWords) -> System.out.println(length + ": " + sortedWords));
    }
}

在上述代码中:

  • supplier 方法返回一个 HashMap 作为中间数据结构。
  • accumulator 方法将每个单词按其长度添加到对应的 List 中。
  • combiner 方法用于合并多个 Map(在并行流的情况下)。
  • finisher 方法对每个 List 进行排序并返回最终的 Map
  • characteristics 方法定义了该 Collector 的特性。 在 main 方法中展示了如何使用这个自定义的 Collector