List :: contains with comparator

Is there any way (method, lambda or elegant design) to find an element in the list based on this comparator?

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 want to replace it with something more elegant.

I do not want to add any dependency, therefore no Guava, "commons", etc. I am really looking for a good way to do this in Java 8.

EDIT: An example of what I find more elegant (here is the usage 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)) { // ... } 
+6
source share
4 answers

As far as I know, there are no built-in functions directly related to this task. Therefore, since you cannot avoid creating utility methods (if you want to reduce code duplication), it is worth considering what kind of useful method can be useful in other scenarios.

eg. if this was my project, I knew that methods for applying a partial function are almost always used, for example:

 public static <T,U,R> Function<U,R> bind(BiFunction<T,U,R> f, T t) { return u -> f.apply(t, u); } 

Using this existing method, the solution might look like this:

 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 would be a method to convert a Comparator to BiPredicate equality and a utility method to partially apply 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

 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 elsewhere in your project. On the other hand, they are so general that similar methods can be added as default methods to functional interfaces in a subsequent release of Java. In this case, your code using these utility methods is ready to upgrade to this newer version.

+5
source

Not sure if this is what you want, but one of the possibilities is to create your own interface that extends Stream and provide the desired method (NOTE: UNTESTED):

 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 can use:

 MyStream.of(someList).containsAny(item, comparator); 

(but this is a lot of code for not really, really)

+1
source

Why do you want to create an additional function in the first place? Just call every time the thread is running.

If you insist, you can use BiPredicate instead of Comparator .

For instance.

 BiPredicate<Integer,Integer> greaterThan = (i,s) -> i > s; 

And change your addition 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 this is more elegant, but it seems to work.

+1
source

You can use the following methods from commons-collections version 4+ :

  • 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 the predicate is true for any element iterable.
0
source

Source: https://habr.com/ru/post/979039/


All Articles