3

我想要两个功能。第一个将给定一个集合,返回满足谓词的元素。谓词可能非常昂贵,并且结果不会被完全消耗,所以我认为最好的做法是返回一个视图。因此,一旦实现,我的方法就是封装了 Guava 的 Collections2.filter 的东西:

Collection<MyElement> getInterestingElements(Collection<MyElement> allElements) {
    return Collections2.filter(allElements, new Predicate<MyElement>() {
        @Override
        public boolean apply(MyElement element) {
            return element.isInteresting();  // call expensive function
        }
    });
}

(班级名称已更改以保护无辜者)

我的第二个函数将调用第一个函数并返回:

  • 如果集合包含零个或多个元素,则为 null。
  • 如果集合仅包含一个元素,则为集合的唯一元素。

也就是说,当且仅当此集合是单例时,此函数才会返回集合的内容。

一个天真的实现是:

MyElement getElementIfOnlyInterestingOne(Collection<MyElement> allElements) {
    Collection<MyElement> interestingElements = getInterestingElements(allElements);

    if (interestingElements.size() != 1){
        return null;
    }

    return Iterables.first(interestingElements, null);
}

但是调用size()will (我认为)评估基础集合的所有元素的谓词,当我只对第一个元素感兴趣时,这是不可接受的。

我可以使用 Iterables.getOnlyElement() ,但是如果集合不是单例,这会抛出异常,这应该经常发生,我认为依靠异常来做到这一点是一种不好的做法。

所以我必须手动迭代,将第一个元素存储在一个变量中,如果有第二个元素,则返回 null。

我的问题是:这很好,但我不是在重新发明轮子吗?番石榴有太多的魔力,这个问题必须由某个isSingletongetSingleElementOrNull某个地方来解决:)

4

3 回答 3

10

“番石榴方式”是使用FluentIterable'firstMatch方法,它返回Optional实例。在你的情况下:

MyElement interestingOrNull = FluentIterable.from(allElements)
    .firstMatch(new Predicate<MyElement>() {
      @Override
      public boolean apply(MyElement element) {
        return element.isInteresting();
      }
    })
    .orNull();

null(甚至更多的“番石榴方式”毕竟不会使用......)

于 2013-02-22T11:26:43.507 回答
7

如果必须按照描述实现该方法,其中必须返回除一个元素之外的任何过滤集合null,那么我能想到的最好的方法就是您已经建议的解决方案。

Collection<MyElement> interestingElements = getInterestingElements(allElements);
Iterator<MyElement> iterator = interestingElements.iterator();
if (!iterator.hasNext()) {
    return null;
}
MyElement first = iterator.next();
if (iterator.hasNext()) { // More than one element
    return null;
} else {
    return first;
}
于 2013-02-21T23:01:25.727 回答
0

当然,上面的 FluentIterable 建议没有处理问题的 size>2 => null 部分。就个人而言,我会使用 Iterables.getOnlyValue 方法。有点乱,但是大大简化了代码,意图也很明确。

于 2013-02-28T00:50:19.923 回答