2014-10-27 58 views
7

有没有一种简单的方法来检查一个元素是否包含在一个迭代器或迭代器中,类似于Collection.contains(Object o)方法?包含用于Iterable和Iterator的方法?

I.e.而不必写:

Iterable<String> data = getData(); 
for (final String name : data) { 
    if (name.equals(myName)) { 
     return true; 
    } 
} 

我想这样写:

Iterable<String> data = getData(); 
if (Collections.contains(data, myName)) { 
    return true; 
} 

我真的很惊讶,有没有这样的事情。

+1

如果你被限制到JDK库,我不相信有这样做的直接手段。 – 2014-10-27 14:06:04

回答

6

在Java 8中,您可以在它打开IterableStream和使用anyMatch

String myName = ... ; 
Iterable<String> data = getData(); 

return StreamSupport.stream(data.spliterator(), false) 
        .anyMatch(name -> myName.equals(name)); 

或使用方法参考,

return StreamSupport.stream(data.spliterator(), false) 
        .anyMatch(myName::equals); 
0

Iterator就像是对集合中元素的指针/引用。它是而不是集合本身。所以,你不能使用iterator.contains()。而且,Iterable接口用于迭代通过集合使用for each每个循环。集合和迭代器/ Iterable是不同的。

0

JavaDoc for Iterable

实现此接口允许一个对象是“的foreach”语句

我很抱歉地说,你正在试图做的是什么目标不可能。

.contains是接口Collection的方法,而不是Iterable,所以也许你可以使用该接口。

3

迭代器是一种可以移动到任何元素集合的元素上的游标。所以它的内部状态主要是指向当前元素的指针。如果你试图找出它是否“包含”某个元素,你将不得不移动光标,因此修改内部状态。通过简单地问一个问题来修改状态肯定是一件坏事。

这甚至与提到的番石榴的问题。它将通过简单地调用contains方法来修改迭代器对象。

另一方面,iterable只是一个告诉编译器需要迭代的接口。在大多数情况下,可迭代对象将是集合本身。如果你想在接口Iterable中添加像“contains”这样的方法,你会得到Collection接口的(简化)版本 - 已经存在。所以这没有必要。

如果您在某处引用了可迭代但需要集合功能的地方停留在代码中,则应考虑重构代码。要么你应该一致地使用接口集合,要么问自己为什么你最好不要在这个时候调用收集方法。所以你的问题很可能是代码设计不理想的结果。

另一方面,我认为使用Iterable作为参数或变量的类型是一件很奇怪的事情。技术上你可以做到这一点,但我认为它只用于循环。

+0

我使用[Guava Splitter]获得一个Iterable(http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Splitter.html#split(java.lang.CharSequence)) ,我不能使用更新的'splitToList',因为我们在公司使用的是旧版本。 – Roland 2014-10-27 14:48:18

+1

那么糟糕的代码设计是由谷歌,他们现在意识到它自己;-) – 2014-10-27 14:58:38

+0

我认为集合类可以添加一个包含方法,接受一个I​​terable。我在谈论收藏,而不是收藏。 – Roland 2014-10-30 09:20:18