首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >List::contains with comparator

List::contains with comparator
EN

Stack Overflow用户
提问于 2014-12-03 18:46:52
回答 4查看 16.3K关注 0票数 13

有没有办法(方法、lambda或优雅的构造)根据给定的比较器在列表中找到元素?

我写了一个这样的方法:

代码语言:javascript
复制
private static <T> boolean contains(List<T> list, T item, Comparator<? super T> comparator) {
    return list.stream()
            .anyMatch(listItem -> comparator.compare(listItem, item) == 0
            );
}

但我希望用更优雅的东西来取代它。

我不想添加任何依赖,所以没有Guava,"commons“等。我真的很想在Java 8中找到一种很好的方式来做到这一点。

编辑:一些我认为更优雅的例子(这里是使用代码):

代码语言:javascript
复制
// sadly, this method doesn't exist
// nor is there a static one in Collections
// but maybe you can think of another way?
if (list.containsSame(item, comparator)) {
    // ...
}
EN

回答 4

Stack Overflow用户

发布于 2014-12-03 22:52:08

据我所知,没有直接解决这一任务的内置功能。因此,由于您无法避免创建实用程序方法(如果您希望减少代码重复),因此值得考虑哪种实用程序方法在其他场景中也是有用的。

例如,如果是我的项目,我知道几乎总是有部分函数应用程序的方法,比如:

代码语言:javascript
复制
public static <T,U,R> Function<U,R> bind(BiFunction<T,U,R> f, T t) {
    return u -> f.apply(t, u);
}

利用此现有方法,解决方案可能如下所示:

代码语言:javascript
复制
static <T> boolean contains(List<T> list, T item, Comparator<? super T> comparator) {
  return list.stream().map(bind(comparator::compare, item))
                      .anyMatch(Predicate.isEqual(0));
}

但这不一定是最好的解决方案。

另一种方法可以是具有用于将Comparator转换为相等BiPredicate的方法和用于BiPredicate的部分应用的实用方法

代码语言:javascript
复制
public static <T> BiPredicate<T,T> match(Comparator<T> f) {
    return (a,b)->f.compare(a, b)==0;
}
public static <T,U> Predicate<U> bind(BiPredicate<T,U> f, T t) {
    return u -> f.test(t, u);
}

然后,contains方法就变得像下面这样简单

代码语言:javascript
复制
static <T> boolean contains(List<T> list, T item, Comparator<? super T> comparator) {
  return list.stream().anyMatch(bind(match(comparator), item));
}

但是,如果实用程序方法也可以在项目的其他地方使用,那么这只是一种简化。另一方面,它们的一般性使得类似的方法可能会作为default方法添加到后续的Java版本中的函数接口。在这种情况下,使用这些实用程序方法的代码已准备好迁移到较新的版本。

票数 11
EN

Stack Overflow用户

发布于 2017-02-14 23:54:48

您可以使用下面的方法from the commons-collections version 4+

  • IterableUtils.contains(Iterable<? extends E> iterable, E object, Equator<? super E> equator) -检查对象是否包含在给定的iterable.
  • IterableUtils.matchesAny(Iterable<E> iterable, Predicate<? super E> predicate)中-如果可迭代的任何元素的谓词为true,则返回true。
票数 3
EN

Stack Overflow用户

发布于 2014-12-03 20:02:54

不确定这是否是您想要的,但一种可能是创建您自己的接口来扩展Stream,并提供您想要的方法(注意:未测试):

代码语言:javascript
复制
public interface MyStream<R>
    extends Stream<R>
{
    // Yay! Static methods in interfaces!
    public static <E> MyStream<E> of(final Collection<E> collection)
    {
        return new MyStreamImpl<E>(collection);
    }

    // Yay! Default methods in interfaces!
    default boolean containsAny(R item, Comparator<? super R> comparator)
    {
        return anyMatch(e -> comparator.compare(item, e) == 0);
    }
}

public class MyStreamImpl<R>
    implements MyStream<R>
{
    private final Stream<R> stream;

    public MyStreamImpl(final Collection<R> collection)
    {
        this.stream = Objects.requireNonNull(collection.stream());
    }

    // delegate all other operations to stream
}

然后你可以使用:

代码语言:javascript
复制
MyStream.of(someList).containsAny(item, comparator);

(但这是大量的代码,实际上不是很多)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27269675

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档