本文介绍了收藏家减少到列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑此类:

@Data
@AllArgsConstructor
@NoArgsConstructor
class User {
    String name;
    String languages;
}

我有一个List<User>,我想减少使用语言的数量.输入:

I have a List<User> and I would like to reduce on languages. Input:

List<User> list = new ArrayList<>();
list.add(new User("sam", "java"));
list.add(new User("sam", "js"));
list.add(new User("apollo", "html"));

预期输出:

[User(name=apollo, languages=html), User(name=sam, languages=java, js)]

我可以使用以下代码实现这一目标:

I can achieve this using following code:

List<User> l = list.stream()
    .collect(Collectors.groupingBy(
         u -> u.name,
         Collectors.reducing((u1, u2) -> 
             new User(u1.name, u1.languages + ", " + u2.languages))))
    .values()
    .stream()
    .filter(user -> user.get() != null)
    .map(user -> user.get())
    .collect(Collectors.toList());

System.out.println(l);

但是我不想创建两个流,可以使用单个流来实现吗?

But I don't want to create two stream, can this be achieved using a single stream?

推荐答案

当然可以,您有两个选择,在这两个选择中,您都必须使用Collect.collectingAndThen从创建的Map中提取正确的值类型.

Of course it is possible, you have two options and in both you have to use Collect.collectingAndThen that extracts the correct value type from a created Map.

您需要首先使用以下lambda表达式:

You need to use the following lambda expression first:

BinaryOperator<User> binaryOperator = (u1, u2) -> 
    new User(u1.getName(), String.join(", ", u1.getLanguages(), u2.getLanguages()));

解决方案:

  1. Collectors.toMapCollectors.collectingAndThenMap<String, User>中提取值:

List<User> l = list.stream()                                       // Stream<User>
    .collect(Collectors.collectingAndThen(
        Collectors.toMap(                                          // Map
            User::getName,                                         // ..name as key
            user -> new User(user.getName(), user.getLanguages()), // ..value as user
            binaryOperator),                                       // ..combined
        map -> new ArrayList<>(map.values())));                    // extracted value

  • Collectors.groupingByCollectors.collectingAndThenCollectors.reducing引起的Map<String, Optional<User>>中提取值:

  • Collectors.groupingBy with Collectors.collectingAndThen extracting values from the Map<String, Optional<User>> caused by Collectors.reducing:

    List<User> ll = list.stream()                     // Stream<User>
        .collect(Collectors.collectingAndThen(
            Collectors.groupingBy(                    // Map<String, Optional<User>>
                User::getName,                        // ... name as key
                Collectors.reducing(binaryOperator)), // ... reduced value
            map -> map.values().stream()              // extracted value
                .filter(Optional::isPresent)          // ... where is Optional present
                .map(Optional::get)                   // ... get it
                .collect(Collectors.toList())));      // ... create a List<User>
    

  • 请注意,我想您使用 java-8 ,可能会使用 java-11 或更高版本.

    Note I suppose you use java-8, there might be a different solution using java-11 or higher.

    这篇关于收藏家减少到列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

    10-22 05:01