简体   繁体   English

使用 Java 8 Stream 从 Map 中检索具有特定属性的值

[英]Retrieving Values from having a particular property from a Map using Java 8 Stream

I have a class UserCourseEntity with a property userId我有一个带有属性userId的 class UserCourseEntity

@AllArgsConstructor
@Getter
@ToString
public static class UserCourseEntity {
    private String userId;
}

And I have a map with UserCourseEntity objects as values.我有一个 map ,其中UserCourseEntity对象作为值。

public final Map<String, UserCourseEntity> userCourses;

Method getUserCoursesByUserID receives userId property of the UserCourseEntity as a parameter.方法getUserCoursesByUserID接收UserCourseEntityuserId属性作为参数。

I want to check if there are values in the userCourses map having userId that matches the giving id in the case-insensitive manner (ie using equalsIgnoreCase() ).我想检查userCourses map 中是否有userId以不区分大小写的方式匹配给定id的值(即使用equalsIgnoreCase() )。

If there are such values, I need to store them into a list, and throw an exception otherwise.如果有这样的值,我需要将它们存储到一个列表中,否则抛出异常。

I'm wonder is it possible to reimplement this code using streams?我想知道是否可以使用流重新实现此代码?

public List<UserCourseEntity> getUserCoursesByUserID(String userId) {
    List<UserCourseEntity> list = new ArrayList<>();
    for (Map.Entry<String, UserCourseEntity> entry : userCourses.entrySet()) {
        UserCourseEntity userCourseEntityValue = entry.getValue();
        String key = entry.getKey();
        boolean isExist = userCourseEntityValue.getUserId().equalsIgnoreCase(userId);
        
        if (!isExist) {
            continue;
        } else {
            if (userCourseEntityValue.getUserId().equalsIgnoreCase(userId)) {
                list.add(userCourses.get(key));
            }
        }
    }
    if (list.isEmpty()) {
        logger.error("No data found");
        throw new SpecificException("No data found with the given details");
    }
    return list;
}

We can achieve it using streams.我们可以使用流来实现它。

For that, we need to create a stream over the map-entries.为此,我们需要在地图条目上创建一个 stream。 Filter the entries that have values with matching userId .过滤具有匹配userId值的条目。 That transform the stream by extracting the value from each entry and collect them into a list.通过从每个条目中提取值并将它们收集到列表中来转换 stream。

Note: there's no way to throw an exception from inside the stream, hence if -statement responsible for that remains on its place.注意:没有办法从 stream 内部抛出异常,因此负责该异常的if语句仍然存在。

That's how it can be implemented:这就是它的实现方式:

public List<UserCourseEntity> getUserCoursesByUserID(String userId) {

    List<UserCourseEntity> courses = userCourses.entrySet().stream()
        .filter(entry -> entry.getValue().getUserId().equalsIgnoreCase(userId))
        .map(Map.Entry::getValue)
        .collect(Collectors.toList()); // or .toList() for Java 16+
    
    if (courses.isEmpty()) {
        logger.error("No data found");
        throw new SpecificException("No data found with the given details");
    }
    
    return courses;
}

Sidenote: from the perspective of class design , it would be cleaner if you had a user object responsible for storing and manipulate information ( retrieving and changing ) regarding their courses.旁注:class 设计的角度来看,如果您有一个用户 object负责存储和操作有关其课程的信息(检索和更改),那将会更干净。

And you can maintain a collection of user, for instance a HashMap associating id with a user .您可以维护一个用户集合,例如将id用户关联的HashMap That would allow accessing a list of courses in a convenient way.这将允许以方便的方式访问课程列表

Iterating over the HashMap s entries ins't the best way of using it.遍历HashMap的条目并不是使用它的最佳方式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM