Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to bind a Java Supplier to an instance of an object?

How can I bind a Java Supplier to an existing instance of an Object? For example, if I want to write my own compareTo() method with this header:

public static int myCompareTo(Object o1, Object o2, Supplier<Comparable> supplier) {...}

I want be able to call it like:

myCompareTo("Hello", "Hello2", String::length);

where String (with the capital letter) is a class and no object. So how can I bind the instance o1 to the supplier?

like image 666
Philipp Niedergesäß Avatar asked Oct 06 '18 19:10

Philipp Niedergesäß


People also ask

How do you pass a supplier in Java?

You can pass in the method with a method reference( create(WhateverClassItIsOn::makeFoo); ), and the variable can be passed in simply using the name create(WhateverClassItIsOn. makeFoo); .

How does Java supplier work?

Java's functional supplier interface can be used any time a function needs to generate a result without any data passed into it. Now, contrast that with Java's functional Consumer interface which does the opposite. The Consumer interface will pass data, but no result will be returned to the calling program.

What is supplier interface in Java?

The Supplier Interface is a part of the java. util. function package which has been introduced since Java 8, to implement functional programming in Java. It represents a function which does not take in any argument but produces a value of type T.

What is the use of supplier?

A supplier is a person or business that provides a product or service to another entity. The role of a supplier in a business is to provide high-quality products from a manufacturer at a good price to a distributor or retailer for resale.


2 Answers

Thanks for your answers. Actually I figured it out now. I wanted to have the supplied object instances (o1 and o2) to execute the given method. I found out that Supplier was the wrong interface instead I had to use Function. Here you can see my working simplified example:

public static <T> int myCompareTo(T o1, T o2, Function<T, Comparable> getter) {
        return getter.apply(o1).compareTo(getter.apply(o2));
}

The reason, the interface has to be Function and not Supplier is, that only Function is equivalent to a lambda expression taking an object and calls the referenced method on the object.

For example, if you define the method reference as:

Function<TypeOfInstance, ReturnTypeOfReferencedMethod> methodReference = TypeOfInstance::referencedMethod();

then the equivalent lambda expression being executed is:

(instance) -> instance.referencedMethod()

Additional Information:

Edit: I know I could have done the same by using Comparator, but this example is very simplified. In my application a Function of this kind is neccessary. I had to create a compareTo function that sorts an ArrayList by more than one attribute because the main sorting attribute may not be unique in the list. I want to share my code with you, because I think it can be a interesting insight for you.

public static <T> int ultimateCompare(T o1, T o2, Function<T, Comparable>... getters) {
    for (Function<T, Comparable> getter : getters) {
        int result = getter.apply(o1).compareTo(getter.apply(o2));
        if (result != 0) return result;
    }
    return 0;
}

With this for example, you can sort a list of persons by last name and if two of them are identical, you can use the first name to sort. With this solution you can change sorting at runtime.

like image 68
Philipp Niedergesäß Avatar answered Sep 22 '22 01:09

Philipp Niedergesäß


Here's what you were searching for (I believe):

public static <T, U extends Comparable<U>> int compare(T o1, T o2, Function<T, U> mapper) {
    return mapper.apply(o1).compareTo(mapper.apply(o2));
}

You can call that like so:

compare("str1", "str2", String::length); // 0
like image 43
steffen Avatar answered Sep 22 '22 01:09

steffen