Java Guava迭代器,并在列表对象内的列表上迭代

Java Guava迭代器,并在列表对象内的列表上迭代,java,iterator,guava,Java,Iterator,Guava,下面的示例代码由3个嵌套for循环组成 for(Continent continent : continentList) { for(Country country : continent.getCountries()) { for(City city : country.getCities()) { //Do stuff with city objects } } } 有没有办法使用Guava和

下面的示例代码由3个嵌套for循环组成

for(Continent continent : continentList) 
{
    for(Country country : continent.getCountries())
    {
        for(City city : country.getCities())
        {
            //Do stuff with city objects
        }
    }
}
有没有办法使用Guava和迭代器来模拟这个嵌套for循环?我一直在努力寻找一个不太幸运的合适的例子,我想知道是否有人能帮我解决这个问题?我的一位同事提到使用过滤器


编辑:修复了示例代码中的小错误

不,没有简单的方法。而且,它将比问题中的for each循环更加冗长


正如Peter Lawrey评论的那样,这几乎肯定会比嵌套循环更简单。除此之外,还发出以下警告:

命令式代码应该是您的默认代码,作为Java的首选 7.除非您完全确定以下情况之一,否则不应使用功能性习惯用法:

  • 使用函数式习惯用法将净节省代码行 为了你的整个项目。移动定义 将一个函数复制到另一个文件或常量也无济于事
  • 为了提高效率,您需要一个延迟计算的转换视图 集合,无法满足显式计算的集合。 此外,您已经阅读并重新阅读了有效Java,第55项,以及 除了遵循这些说明之外,你实际上已经做到了 基准测试证明这个版本更快,并且可以引用 数字证明了这一点
使用番石榴的功能性食品时,请确保 实用程序,传统的命令式做事方式不是 更具可读性。试着把它写出来。那么糟糕吗?那是更多吗 比你那荒谬笨拙的功能性方法更具可读性 要试试吗

然而,如果您坚持忽略建议,您可以使用类似这样的怪物(注意,我实际上并没有尝试编译或运行这个):

fluenterable.from(列表)
.transform(新函数(){
公共无效申请(大陆){
返回fluentitable.from(contraction.getCountries())
.transform(新函数(){
公共无效申请(国家/地区){
返回fluentitable.from(country.getCities())
.transform(新函数(){
公共无效申请(城市){
//用城市物体做东西
返回null;
}
});
}
});
}
});
现在问问你自己:你想维持哪一个?哪一个将是最有效的


番石榴的功能性习语有一些有效的用例。将Java替换为循环(甚至嵌套为循环)不是其中之一。

另一个怪物,使用AbstractIterator:

    class CityIterable implements Iterable<City> {
        List<Continent> continents;

        CityIterable(List<Continent> continents) {
            this.continents = continents;
        }

        @Override
        public Iterator<City> iterator() {
            return new AbstractIterator<City>() {
                Iterator<Continent> continentIterator = continents.iterator();
                Iterator<Country> countryIterator;
                Iterator<City> cityIterator;

                @Override
                protected City computeNext() {
                    if (cityIterator != null && cityIterator.hasNext()) {
                        return cityIterator.next();
                    }
                    if (countryIterator != null && countryIterator.hasNext()) {
                        cityIterator = countryIterator.next().getCities().iterator();
                        return computeNext();
                    }
                    if (continentIterator.hasNext()) {
                        countryIterator = continentIterator.next().getCountries().iterator();
                        return computeNext();
                    }
                    return endOfData();
                }
            };
        }
    }
考虑到这种可怕的情况,请遵循ig0774的建议并保留嵌套循环


另外,不需要过滤器。

我同意其他人的观点,嵌套循环是最有效的方式。但是:我会将每个循环级别提取到一个单独的方法中,以保持可读性并确保每个方法只做一件事:

public void doStuffWithWorld(World world){
    for (Continent continent : world.getContinents()) {
        doStuffWithContinent(continent);
    }
}

private void doStuffWithContinent(Continent continent) {
    for (Country country : continent.getCountries()) {
        doStuffWithCountry(country);
    }
}

private void doStuffWithCountry(Country country) {
    for(City city : country.getCities()){
        doStuffWithCity(city);
    }
}

private void doStuffWithCity(City city) {
    // do stuff here
}

如果您需要在不同的级别执行某些状态,您有几个选项:将它们放在包含类的成员字段中,向所有方法传递第二个参数,这些方法可以是映射或自定义对象。

您可以为以下对象定义静态函数:
•获取大陆、大陆或功能中的国家(
•getCities()位于国家/地区、国家/地区或职能部门

现在你可以做一些像

FluentIterable.from(continentList)
    .transformAndConcat(Continent.getCountriesFunction())
    .transformAndConcat(Country.getCitiesFunction())
    . //filter //tranform //find //toList() //etc.
如果:
•像这样(更多)使用番石榴。
•并对定义函数和谓词的位置有一定的规则/想法。
•有各种各样(复杂)的东西要过滤或搜索。
然后,它可以是一个巨大的恩惠,可以使许多情况下相当容易一点。我知道我很高兴我做到了。


如果你很少使用它,那么我必须同意@Louis Wasserman。那就不值得这么麻烦了。此外,像其他示例一样,将函数和谓词定义为匿名内部类。。。非常难看。

您可以嵌套映射。至少对于外部循环来说,作为嵌套循环可能更简单。在第3行中,这不应该是“Continental.getCountries()”?您可以使用guavas“transform”和“concat”创建一个三元组列表,然后对其进行迭代,但至少对于Java 7,代码将相当难看。我会继续使用嵌套循环。使用,您可以链接转换,而不是嵌套它们。@FrankPavageau:True。但是,即使这会更干净一点,它仍然会比嵌套循环更难看,可读性更低。@ig0774感谢专业提示:)我真的很喜欢你的建议;如果需要的话,还将对每个单独的活套功能进行单元测试。谢谢:)
public void doStuffWithWorld(World world){
    for (Continent continent : world.getContinents()) {
        doStuffWithContinent(continent);
    }
}

private void doStuffWithContinent(Continent continent) {
    for (Country country : continent.getCountries()) {
        doStuffWithCountry(country);
    }
}

private void doStuffWithCountry(Country country) {
    for(City city : country.getCities()){
        doStuffWithCity(city);
    }
}

private void doStuffWithCity(City city) {
    // do stuff here
}
FluentIterable.from(continentList)
    .transformAndConcat(Continent.getCountriesFunction())
    .transformAndConcat(Country.getCitiesFunction())
    . //filter //tranform //find //toList() //etc.