Is possible to know the size of a stream without using a terminal operation

生来就可爱ヽ(ⅴ<●) 提交于 2020-07-29 17:06:09

问题


I have 3 interfaces

public interface IGhOrg {
    int getId();

    String getLogin();

    String getName();

    String getLocation();

    Stream<IGhRepo> getRepos();
}

public interface IGhRepo {
    int getId();

    int getSize();

    int getWatchersCount();

    String getLanguage();

    Stream<IGhUser> getContributors();
}

public interface IGhUser {
    int getId();

    String getLogin();

    String getName();

    String getCompany();

    Stream<IGhOrg> getOrgs();
}

and I need to implement Optional<IGhRepo> highestContributors(Stream<IGhOrg> organizations)

this method returns a IGhRepo with most Contributors(getContributors())

I tried this

Optional<IGhRepo> highestContributors(Stream<IGhOrg> organizations){
    return organizations
            .flatMap(IGhOrg::getRepos)
            .max((repo1,repo2)-> (int)repo1.getContributors().count() - (int)repo2.getContributors().count() );
}

but it gives me the

java.lang.IllegalStateException: stream has already been operated upon or closed

I understand that count() is a terminal operation in Stream but I can't solve this problem, please help!

thanks


回答1:


You don't specify this, but it looks like some or possibly all of the interface methods that return Stream<...> values don't return a fresh stream each time they are called.

This seems problematic to me from an API point of view, as it means each of these streams, and a fair chunk of the object's functionality can be used at most once.

You may be able to solve the particular problem you are having by ensuring that the stream from each object is used only once in the method, something like this:

Optional<IGhRepo> highestContributors(Stream<IGhOrg> organizations) {
  return organizations
      .flatMap(IGhOrg::getRepos)
      .distinct()
      .map(repo -> new AbstractMap.SimpleEntry<>(repo, repo.getContributors().count()))
      .max(Map.Entry.comparingByValue())
      .map(Map.Entry::getKey);
}

Unfortunately it looks like you will now be stuck if you want to (for example) print a list of the contributors, as the stream returned from getContributors() for the returned IGhRepo has already been consumed.

You might want to consider having your implementation objects return a fresh stream each time a stream returning method is called.




回答2:


Is possible to know the size of a stream without using a terminal operation

No it's not, because streams can be infinite or generate output on demand. It's not necessary that they are backed by collections.

but it gives me the

java.lang.IllegalStateException: stream has already been operated upon or closed

That's becase you are returning the same stream instance on each method invocation. You should return a new Stream instead.

I understand that count() is a terminal operation in Stream but I can't solve this problem, please help!

IMHO you are misusing the streams here. Performance and simplicity wise it's much better that you return some Collection<XXX> instead of Stream<XXX>




回答3:


NO.

This is not possible to know the size of a stream in java.

As mentioned in java 8 stream docs

No storage. A stream is not a data structure that stores elements; instead, it conveys elements from a source such as a data structure, an array, a generator function, or an I/O channel, through a pipeline of computational operations.



来源:https://stackoverflow.com/questions/38044849/is-possible-to-know-the-size-of-a-stream-without-using-a-terminal-operation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!