Iterators.filter vs for-each



也许这是一个明显或愚蠢的问题,所以我提前道歉。

让我们假设我有以下两种方法来迭代具有简单条件的集合:

<标题> 1
Predicate<SomeObject> pred1 = new Predicate<SomeObject> () {... some condition_1 ...};
Predicate<SomeObject> pred2 = new Predicate<SomeObject> () {... some condition_2 ...};
Iterator<SomeObject> newIterator = Iterators.filter(iterator, pred1);
... do something like Sets.newHashSet(newIterator) ...
newIterator = Iterators.filter(iterator, pred2);
... do something like Sets.newHashSet(newIterator) ...
<标题> 2 h1> 说2号比1号快对吗?

谢谢你的回答!

命令式版本会快一些,但是快多少很难确定。在我的测试中,一旦启动,两个版本都能在1.1微秒内返回。命令式版本方法在95%的情况下(1,000,000个随机执行的运行)运行速度超过5.15 micros,而FluentIterable版本在95%的情况下运行速度超过6.6 micros。

Guava可以非常快,特别是如果谓词和函数可以静态定义。

在下面的例子中,请注意谓词组合和FluentIterable的使用。

FluentIterable特别有吸引力,因为它的用法可以用Java 8流替换,只需要很少的修改。

public static class SomeObject {
    private final String someString;
    public SomeObject(final String someString) {
        this.someString = someString;
    }
    public String getSomeString() {
        return this.someString;
    }
    @Override
    public String toString() {
        return this.someString;
    }
}
public static final Predicate<SomeObject> CONTAINS_A_FILTER = new Predicate<GuavaExample.SomeObject>() {
    @Override
    public boolean apply(final SomeObject someObject) {
        return someObject.getSomeString()
            .contains("A");
    }
};
public static final Predicate<SomeObject> CONTAINS_B_FILTER = new Predicate<GuavaExample.SomeObject>() {
    @Override
    public boolean apply(final SomeObject someObject) {
        return someObject.getSomeString()
            .contains("B");
    }
};
public static final Predicate<SomeObject> CONTAINS_A_AND_B_FILTER = Predicates.and(CONTAINS_A_FILTER,
        CONTAINS_B_FILTER);
public static final Predicate<SomeObject> CONTAINS_A_OR_B_FILTER = Predicates.or(CONTAINS_A_FILTER,
        CONTAINS_B_FILTER);
public static void main(final String... args) {
   final List<SomeObject> someObjects = ImmutableList.of(new SomeObject("A"), new SomeObject("AB"),
            new SomeObject("B"), new SomeObject("C"));
    final Set<SomeObject> containsAandB = FluentIterable.from(someObjects)
            .filter(CONTAINS_A_AND_B_FILTER)
            .toSet();
    // prints [AB]
    System.out.println(containsAandB);
    final Set<SomeObject> containsAOrB = FluentIterable.from(someObjects)
            .filter(CONTAINS_A_OR_B_FILTER)
            .toSet();
    // prints [A, AB, B]
    System.out.println(containsAOrB);
}

如果我说错了请指正,但我认为#2可能更快。

例#1对集合进行了两次过滤。每次过滤算作一次迭代。因此,您很可能会花费更多的时间来过滤它们。我可能在这一点上是非常错误的,因为我看到一个问题,为什么迭代排序集合比未排序集合快,但希望有人能详细说明。

然而,例#2只迭代它一次。

别相信我的话,但我很确定我在这里是正确的。

最新更新