1

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 (i.e. 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;
}
Alexander Ivanchenko
  • 25,667
  • 5
  • 22
  • 46

1 Answers1

0

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 HashMaps entries ins't the best way of using it.

Alexander Ivanchenko
  • 25,667
  • 5
  • 22
  • 46