1

I have a string field userId, I want to add it to the list of strings which is formed by stream like this user.getFollowing.stream().toList()

public List<Post> getAllPosts(String userId) {
    User user = this.findUserById(userId);
    System.out.printf("Finding all posts created by %s%n", userId);
    
    if (user != null) {
        List<String> userList = user.getFollowing().stream().toList();

        userList.add(userId).stream().toList();

        List<Post> allPostsList = postService.findPostsCreatedByMultipleUsers(userList);
        System.out.printf("Returning %d posts created by %s%n", allPostsList.size(), userId);
        return allPostsList;
    } else {
        System.out.printf("Unable to find user by id %s%n", userId);
        return null;
    }
}
Nowhere Man
  • 19,170
  • 9
  • 17
  • 42
Md Sakib
  • 25
  • 6
  • I just want to add userId field to the list of string formed by stream (in this i somehow want to add user id ... user.getFollowing().stream.toList()) – Md Sakib Dec 21 '21 at 06:33
  • 1
    Please have a look at https://stackoverflow.com/editing-help, and try to format your question accordingly. – maloomeister Dec 21 '21 at 06:40

1 Answers1

3

There are several possible solutions:

  1. stream::toList returns an immutable list, so if it is replaced by a mutable list, userId may be just added:
List<String> userList = user.getFollowing().stream().collect(Collectors.toCollection(ArrayList::new));
userList.add(userId);
// ...
  1. Use Stream::concat to concatenate two streams, the second is created from userId using Stream.of:
List<String> userList = Stream.concat(
        user.getFollowing().stream(),
        Stream.of(userId)
    )
    .toList();

However, the simplest solution does not require Stream API at all:

List<String> userList = new ArrayList<>(user.getFollowing());
userList.add(userId);
Nowhere Man
  • 19,170
  • 9
  • 17
  • 42
  • 1
    `collect(Collectors.toList())` returns a list with [**no guarantees on** the type, **mutability**, serializability, or thread-safety](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/stream/Collectors.html#toList()), so it should not be suggested as solution to get a mutable list. `collect(Collectors.toCollection(ArrayList::new))` would be a valid solution guaranteeing a mutable list. However, it’s a typical case of overengineering with streams. `List userList = new ArrayList<>(user.getFollowing()); userList.add(userId);` does the job as well. – Holger Dec 21 '21 at 11:29
  • No guarantees, but still returning [ArrayList with `ArrayList::new`](https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/util/stream/Collectors.java#L280). Also impressed by [`Stream::toList`](https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/util/stream/Stream.java#L1198) implementation: `return (List) Collections.unmodifiableList(new ArrayList<>(Arrays.asList(this.toArray())));` – Nowhere Man Dec 21 '21 at 12:33
  • 2
    It does return an `ArrayList` in the reference implementation, but you should not rely on implementation details, especially when the documentation explicitly says that it is not guaranteed. The `Stream::toList` implementation you’re referring to is the default implementation you’ll probably never encounter in practice. The actual implementation you’ll end up is far better. But still, the default [has been discussed here](https://stackoverflow.com/questions/65741773/would-stream-tolist-perform-better-than-collectors-tolist#comment116293110_65741773). – Holger Dec 21 '21 at 12:42