使用Java流API的Java收集实用程序

6l7fqoea  于 2023-02-14  发布在  Java
关注(0)|答案(2)|浏览(120)

我正在尝试编写自己的CollectionUtils帮助器类,其他应用程序将使用它。

public static <T, K, V> 
    Map<K, List<V>> listToMap(List<T> inputList, 
            Function<? super T, ? extends K> keyMapper, 
            Function<? super T, ? extends V> valueMapper)
    {
        Collector c = Collectors.toMap(keyMapper, valueMapper);
        return inputList.stream()
                .collect(c);
        
        
    }
    
    public void test()
    {
        // trying to get a Map<String, List<String>> showing student's name and their activities.
        listToMap(StudentDatabase.getAllStudents(), Student::getName, Student::getActivites);
    }

然而,我遇到了很多编译错误,我不知道如何解决。我可以在这里得到一些帮助吗?有没有任何第三方库已经这样做了(但它必须使用java流API),我可以使用,所以我不需要写自己的?
我尝试了以上和有编译问题。

mzmfm0qo

mzmfm0qo1#

当前的代码有几个问题:

  1. Collector接口是泛型的。你应该像对待代码中的其他泛型类型一样参数化它。更多信息请参见What is a raw type and why shouldn't we use it?
  • 您已经将返回类型定义为Map<K, List<V>>,这似乎表明您正在尝试实现一个分组操作,但是,代码中还有其他三个部分表明并非如此:
  • 您使用Collectors#toMap(Function,Function)
  • valueMapperMap到V,而不是List<V>
  • 您使用Student::getActivities作为valueMapper的参数来调用listToMap,我只能假设该方法返回活动的列表(或其他集合)。

因此,考虑到所有这些,您应该将返回类型更改为Map<K, V>,这将使调用者完全控制map的值类型,而不是强制他们使用列表,但是如果您 * 正在 * 尝试实现分组操作,并且您总是希望值类型为List<V>,则考虑使用Collectors#groupingBy(Function,Collector)
解决这两个问题会给你带来如下结果:

public static <T, K, V> Map<K, V> listToMap(
        List<T> list,
        Function<? super T, ? extends K> keyMapper,
        Function<? super T, ? extends V> valueMapper) {
    Collector<T, ?, Map<K, V>> collector = Collectors.toMap(keyMapper, valueMapper);
    return list.stream().collect(collector);
}

下面是一个使用上述方法的最小示例:

import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collector;
import java.util.stream.Collectors;

public class Main {

    public record Student(String name, List<String> activities) {}

    public static <T, K, V> Map<K, V> listToMap(
            List<T> list, 
            Function<? super T, ? extends K> keyMapper, 
            Function<? super T, ? extends V> valueMapper) {
        Collector<T, ?, Map<K, V>> collector = Collectors.toMap(keyMapper, valueMapper);
        return list.stream().collect(collector);
    }

    public static void main(String[] args) {
        List<Student> students = List.of(
            new Student("John", List.of("Piano", "Running")),
            new Student("Jane", List.of("Soccer", "Video Games")),
            new Student("Bob", List.of("Snowboarding"))
        );
        Map<String, List<String>> map = listToMap(students, Student::name, Student::activities);
        System.out.println(map);
    }
}

输出:

{Bob=[Snowboarding], John=[Piano, Running], Jane=[Soccer, Video Games]}
u4vypkhs

u4vypkhs2#

该方法应返回Map而不是Collector。另外,Collectors.toMap不足以将List转换为List的Map。您需要使用groupingBy收集器而不是toMap。

return inputList.stream().collect(Collectors.groupingBy(keyMapper, Collectors.mapping(valueMapper, Collectors.toList())));

相关问题