简体   繁体   中英

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

I have a class UserCourseEntity with a property userId

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

And I have a map with UserCourseEntity objects as values.

public final Map<String, UserCourseEntity> userCourses;

Method getUserCoursesByUserID receives userId property of the UserCourseEntity as a parameter.

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() ).

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. Filter the entries that have values with matching userId . That transform the stream by extracting the value from each entry and collect them into a list.

Note: there's no way to throw an exception from inside the stream, hence if -statement responsible for that remains on its place.

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.

And you can maintain a collection of user, for instance a HashMap associating id with a user . 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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