0

References


This is Predicate Functional Interface's abstract method. It gets one argument T t and return boolean.

boolean     test​(T t)  
    Evaluates this predicate on the given argument.

But, in this example, String::isEmpty does not get any argument but it is instance method of String.

Predicate<String> p = String::isEmpty;

I can infer that in Java, this type of method can apply to Functional Interface with one argument.

And, is there any examples of one argument Functional Interface with the function has one argument not like upper example?

varvir
  • 65
  • 1
  • 8
  • You're wrong about String::isEmpty not being a standard Predicate...not taking a single argument. It takes the String it's testing as its single argument. It's equivalent to the lambda `(String s) -> !s.isEmpty()` – CryptoFool Oct 21 '20 at 01:46
  • "*..is there any examples of one argument Functional Interface with the function has one argument not like upper example*?" something like `Predicate isA = "A"::equalsIgnoreCase;`? – Pshemo Oct 21 '20 at 01:55
  • @Pshemo - that's going in the other direction, actually. That proves that a Predicate CAN take zero parameters. That was beside my point. My point was only that String::isEmpty is not such a case. – CryptoFool Oct 21 '20 at 02:00
  • @Steve Sorry but I am not sure what you mean (may be too tired now). Anyway my guess was that OP was asking for example of method which takes one parameter since `isEmpty` doesn't take any my *suggestion* was `equalsIgnoreCase` which takes one. – Pshemo Oct 21 '20 at 02:04
  • @Pshemo - I just realized that that's not a "zero parameter" case, as it still requires a String as input to test against "A". I didn't realize, however, that you could do that...use a method that takes a single parameter (in addition to the receiver String) and then you specify the receiver String explicitly. That's cool! – CryptoFool Oct 21 '20 at 02:07
  • @Steve In that case [this example](https://stackoverflow.com/questions/30053487/how-to-check-if-exists-any-duplicate-in-java-8-streams/30053822#comment48222350_30053822) may also interest you :) (how people come up with code like `new HashSet<>()::add` ...) – Pshemo Oct 21 '20 at 02:11
  • That's sick! I love how it's using a `HashSet` that is never going to be seen or used...that the only reason it exists is to have its `add` method fail! I see that there's some question as to if it's technically legal to have a Predicate that relies on preserved state, and of course, it wouldn't work if mutiprocessed, but it's really cool either way. - Do you know of anywhere that this technique of supplying a pre-bound method as a Functional Interface is more formally presented? - I'm wondering if it's something the compiler has to allow for or if it naturally falls out of the other cases. – CryptoFool Oct 21 '20 at 03:11

2 Answers2

0

You can do Function<T, R> where R is the return type and T is the argument type.
So R result = fnc.apply(k) where k is of type T.

Function<Integer, List<Integer>> fnc =  n-> new ArrayList<>(List.of(n));
List<Integer> list = fnc.apply(23);
System.out.println(list);

prints

[23]

But you can also do this, just like in your example.

Function<Integer, List<Integer>> fnc2 = fnc::apply;
fnc2.apply(44); // returns a list which contains 44

EXTRA DETAILS

Consider the following class. One static and one instance method.

class TestClass {
    public int prod(int a) {
        return a * 33;
    }
    
    public static int mult(int a) {
        return a * 44;
    }
}

To create a Lambda for the static, do the following:

// use unaryOperator since return type are argument are the same
UnaryOperator<Integer> fnc = TestClass::mult;
int result = fnc.apply(10); // returns 440

Now do an instance version.

UnaryOperator<Integer> inst = tc::prod;
inst.apply(10);
result = inst.apply(10); // returns 330

Now a special case using a static type reference.
to an instance method.


// This requires 2 arguments. The instance
// and the argument to the method.a

BiFunction<TestClass, Integer, Integer> stat = TestClass::prod
result = stat.apply(tc, 12); // result is 396
varvir
  • 65
  • 1
  • 8
WJS
  • 36,363
  • 4
  • 24
  • 39
  • `::` can be used at instance(`fnc`) not only class name? I have another confusion with `Function> fnc2 = fnc::apply;`. Can you explain me further more? – varvir Oct 21 '20 at 02:11
  • It is just assigning the method reference of the apply method in the functional interface. You would use the class name for static methods and an instance for the instance method. – WJS Oct 21 '20 at 02:36
  • 1
    Thanks for the detailed answer. @WJS `BiFunction stat = TestClass::mult` should be fixed to `TestClass::prod`. @Steve's answer is more suitable to my original question, but your answer has more and great information for Java Functional Interface newbies. – varvir Oct 21 '20 at 04:22
0

There are three forms that a Predicate can take. Here they are for isEmpty on a String:

1- A formal functional interface:

Predicate<String> somePredicate = new Predicate<String>() {
    @Override
    public boolean test(String s) {
        return s.isEmpty();
    }
};

2- A lambda:

(String s) -> s.isEmpty()

3- A method reference

String::isEmpty

These have identical function and can each be passed when a Predicate<String> is required.

The third doesn't apply if the underlying function is not a method on an object.

CryptoFool
  • 21,719
  • 5
  • 26
  • 44