java 列表::包含比较器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27269675/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
List::contains with comparator
提问by ymajoros
Is there any way (method, lambda, or elegant construct) to find an element in a list based on a given comparator?
有什么方法(方法、lambda 或优雅的构造)可以根据给定的比较器在列表中查找元素?
I wrote a method like this:
我写了一个这样的方法:
private static <T> boolean contains(List<T> list, T item, Comparator<? super T> comparator) {
return list.stream()
.anyMatch(listItem -> comparator.compare(listItem, item) == 0
);
}
But I'm looking to replace it with something that would be more elegant.
但我希望用更优雅的东西代替它。
I don't want to add any dependency, so no Guava, "commons", etc. I'm really looking for a pretty way to do this in Java 8.
我不想添加任何依赖项,所以没有 Guava、“commons”等。我真的在寻找一种在 Java 8 中做到这一点的漂亮方法。
EDIT: Some example of what I'd consider more elegant (here is the using code):
编辑:一些我认为更优雅的例子(这是使用代码):
// 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)) {
// ...
}
回答by Holger
As far as I know, there is no built-in functionality directly addressing this task. So since you can't avoid creating utility methods (if you want reduce code duplication), it's worth thinking about which kind of utility method could be useful in other scenarios as well.
据我所知,没有直接解决此任务的内置功能。因此,由于您无法避免创建实用程序方法(如果您想减少代码重复),那么值得考虑哪种实用程序方法在其他场景中也有用。
E.g. if it was my project I knew there are almost always methods for partial function application flying around, like:
例如,如果这是我的项目,我知道几乎总是有部分函数应用程序飞来飞去的方法,例如:
public static <T,U,R> Function<U,R> bind(BiFunction<T,U,R> f, T t) {
return u -> f.apply(t, u);
}
Utilizing this existing method, a solution could look like:
利用这种现有方法,解决方案可能如下所示:
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));
}
But this is not necessarily the best solution.
但这不一定是最好的解决方案。
Another approach could be to have a method for converting a Comparator
into an equality BiPredicate
and a utility method for partial application of a BiPredicate
:
另一种方法可能是将 aComparator
转换为等式BiPredicate
的方法和部分应用 a 的实用方法BiPredicate
:
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);
}
Then the contains
method becomes as simple as
那么contains
方法就变得简单了
static <T> boolean contains(List<T> list, T item, Comparator<? super T> comparator) {
return list.stream().anyMatch(bind(match(comparator), item));
}
But this is only a simplification if the utility methods can be used at other places of your project as well. On the other hand, they are of such a general nature that similar methods might be added as default
methods to the function interfaces in a subsequent Java release. In this case your code using such utility methods is prepared for migration to that newer version.
但是,如果实用程序方法也可以在项目的其他地方使用,那么这只是一种简化。另一方面,它们具有如此普遍的性质,以至于default
在随后的 Java 版本中,类似的方法可能会作为方法添加到函数接口中。在这种情况下,您使用此类实用程序方法的代码已准备好迁移到该较新版本。
回答by Igor Luzhanov
You can use the next methods from the commons-collections
version 4+:
您可以使用下一个方法从commons-collections
4.0以上的版本:
IterableUtils.contains(Iterable<? extends E> iterable, E object, Equator<? super E> equator)
- Checks if the object is contained in the given iterable.IterableUtils.matchesAny(Iterable<E> iterable, Predicate<? super E> predicate)
- Answers true if a predicate is true for any element of the iterable.
IterableUtils.contains(Iterable<? extends E> iterable, E object, Equator<? super E> equator)
- 检查对象是否包含在给定的可迭代对象中。IterableUtils.matchesAny(Iterable<E> iterable, Predicate<? super E> predicate)
- 如果谓词对可迭代对象的任何元素都为真,则回答为真。
回答by fge
Not sure whether this is what you want, but one possibility is to create your own interface extending Stream
and provide the method you want (NOTE: UNTESTED):
不确定这是否是您想要的,但一种可能性是创建您自己的接口扩展Stream
并提供您想要的方法(注意:未经测试):
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
}
Then you could use:
然后你可以使用:
MyStream.of(someList).containsAny(item, comparator);
(but that's a lot of code for not much, really)
(但那是很多代码,实际上并不多)
回答by giannis christofakis
Why do you want to create an extra function in first place? Just call each time the stream functions.
为什么首先要创建一个额外的功能?每次都调用流函数。
If you insist, instead of a Comparator
you can use a BiPredicate
.
如果您坚持,Comparator
您可以使用 a代替a BiPredicate
。
For example.
例如。
BiPredicate<Integer,Integer> greaterThan = (i,s) -> i > s;
And change your contain function to something like
并将您的包含功能更改为类似
private static <T> boolean containsp(List<T> list, T item, BiPredicate<? super T,? super T> biPredicate) {
return list.stream().filter(l-> biPredicate.test(l,item) ).findFirst().isPresent();
}
I don't know if it's more elegant but it seems to work.
我不知道它是否更优雅,但它似乎有效。