可以在不使用终端操作的情况下知道流的大小

Mau*_*ida 4 java-8 java-stream

我有3个接口

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();
}
Run Code Online (Sandbox Code Playgroud)

我需要实施 Optional<IGhRepo> highestContributors(Stream<IGhOrg> organizations)

此方法返回一个包含大多数贡献者的 IGhRepo(getContributors())

我试过这个

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

但它给了我

java.lang.IllegalStateException: 流已经被操作或关闭

我知道count()是Stream中的一个终端操作但是我无法解决这个问题,请帮忙!

谢谢

Sve*_*rev 5

可以在不使用终端操作的情况下知道流的大小

不,不是,因为流可以是无限的,也可以按需生成输出。它们没有必要由集合支持。

但它给了我

java.lang.IllegalStateException: stream has already been operated upon or closed
Run Code Online (Sandbox Code Playgroud)

那是因为您在每个方法调用中都返回相同的流实例。您应该返回一个新的 Stream。

我知道count()是Stream中的一个终端操作但是我无法解决这个问题,请帮忙!

恕我直言,你在这里滥用流。性能和简单性明智,您返回一些Collection<XXX>而不是Stream<XXX>


msa*_*ord 3

您没有指定这一点,但看起来某些或可能所有返回Stream<...>值的接口方法在每次调用时都不会返回新的流。

从 API 的角度来看,这对我来说似乎是有问题的,因为这意味着每个流以及对象的大部分功能最多只能使用一次。

您可以通过确保每个对象的流在方法中仅使用一次来解决您遇到的特定问题,如下所示:

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);
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,如果您想(例如)打印贡献者列表,您现在似乎会陷入困境,因为从返回的流getContributors()IGhRepo被消耗。

您可能需要考虑让您的实现对象在每次调用流返回方法时返回一个新的流。