Passing arguments to Method References - java

Given this method:
private static Integer getVal(Integer a, Integer b){
return a + b;
}
which can be called as a lambda:
a -> getVal(1, 2)
Is there anyway of turning this into a method reference, something like:
Class::getVal
Thanks

Well, if you are passing constants to the method call, you can create another method that calls the original method:
private static Integer getVal (Integer a) {
return getVal(1,2);
}
then you can use method reference for the second method.
i.e. you can change
a -> getVal(1, 2)
to
ClassName::getVal
That said, it doesn't make much sense.
P.S., it's not clear what's the purpose of a in your lambda expression, since you are ignoring it.
In general you can pass a method reference of a given method if it matches the signature of the single method of the required functional interface.
Example:
public static Integer apply (BinaryOperator<Integer> op, Integer a, Integer b)
{
return op.apply(a,b);
}
Now you can call:
apply(ClassName::getVal)
with your original method.

Here is an example.
interface Operator {
int operate(int a, int b);
}
class Calc {
public static int add(int a, int b) {
return a + b;
}
}
class Main {
public static void main(String[] args) {
// using method reference
int result = operate(1, 2, Calc::add);
// using lambda
int result = operate(1, 2, (a, b) -> Calc.add(a, b));
}
static int operate(int a, int b, Operator operator) {
return operator.operate(a, b);
}
}
You need a functional interface to use method reference (In this example Operator). And you also need a method which accepts an instance of the functional interface as its parermater (In this example operate(int a, int b, Operator operator).
UPDATE
If you need an object wrapper, just change the operate method to
static int operate(ObjectWrapper wrapper, Operator operator) {
return operator.operate(wrapper.getA(), wrapper.getB());
}
And then call the operate method:
int result = operate(wrapper, Calc::add);

getVal() will only be usable as a method reference, in places where a functional interface of an applicable type is expected, such as BiFunction or IntBinaryOperator, or a custom functional interface (as in the answer of zhh)
Example:
public static void main(String[] args) {
Integer result1 = calculate(1, 2, Second::getVal);
Integer result2 = calculateAsInt(1, 2, Second::getVal);
}
private static Integer getVal(Integer a, Integer b){
return a + b;
}
private static Integer calculate(Integer a, Integer b, BinaryOperator<Integer> operator) {
return operator.apply(a, b);
}
private static int calculateAsInt(int a, Integer b, IntBinaryOperator operator) {
return operator.applyAsInt(a, b);
}

Related

How to pass argument in Method_reference in Java 8 for user defined interface and method

My code is something like this,
#FunctionalInterface
interface MathOperation2 {
int operation2(int a, int b, int c);
}
public class Method_reference_demo {
private static int operate2(int a, int b, int c, MathOperation2 obj)
{
return obj.operation2(a, b, c);
}
private void Method_reference_demo01()
{
MathOperation2 mo2 = Method_reference_demo::operate2;
mo2.operation2(2,3,4);
}
}
is there anyway I can make it work by passing parameter through last two lines.
means below lines.
MathOperation2 mo2 = Method_reference_demo::operate2;
mo2.operation2(2,3,4);
I want above snippet as working code.
NOTE: I can't change any line of code except these two lines and want to use Java 8 Method reference.
Bottom line:- You need to provide an implementation of the interface at some point in time to make use of it.
The line of code
MathOperation2 mo2 = Method_reference_demo::operate2
in an invalid declaration, since the signature of the operate2 method
int operate2(int a, int b, int c, MathOperation2 obj)
expects a MathOperation2 to be passed to the method as well.
Note, it can work if you change the signature to remove the last parameter, but that would make it inefficient as one would be better defining the abstract method of the interface itself which follows the same signature then.
I can't change any line of code except these two lines
You can then rather define your interface as :
MathOperation2 mo2 = (a, b, c) -> {
return 0; // perform the operation with a, b and c here
};
System.out.println(mo2.operation2(2, 3, 4)); // just to print the output
for e.g., to add three integers the representation would be:
MathOperation2 mo2 = (a, b, c) -> a + b + c;
System.out.println(mo2.operation2(2, 3, 4)); // would print '9'
(From comments) In terms of method references, the example would translate into something on the lines :
private static int operate2(int a, int b, int c) { // <<-- notice the method signature
return a + b + c; // <<-- and a definition
}
private void Method_reference_demo01() {
MathOperation2 mo2 = Method_reference_demo::operate2;
System.out.println(mo2.operation2(2, 3, 4)); // prints '9'
}
The method reference, MathOperation2 mo2 should point to an implementation of the method, int operation2(int a, int b, int c) i.e. you can do something like
#FunctionalInterface
interface MathOperation2 {
int operation2(int a, int b, int c);
}
public class Main {
private static int operate2(int a, int b, int c) {
return a + b + c;
}
private static void methodReferenceDemo01() {
MathOperation2 mo2 = Main::operate2;
System.out.println(mo2.operation2(2, 3, 4));
}
public static void main(String[] args) {
methodReferenceDemo01();
}
}
But it does not fulfill your requirement 100% as you have mentioned:
I can't change any line of code except these two lines
On a side note, you should follow the Java naming conventions e.g. the method name, Method_reference_demo01 does not follow the conventions; it can be named as methodReferenceDemo01.

Provide arguments with a method

Is there a way in Java to create a method that would return the list of parameters of another method such that I am able to call
anotherMethod(method())
where anotherMethod has arbitrary arguments like
public void anotherMethod(int a, int b, String c)
And what is if the types stay the same, like with
public int add(int a, int b, int c)
If there is no such way, how could I model the list of parameters such that it would work? Is it a List or an array or something else?
If the number of parameters is fixed at the call site, you could use varargs
int add(int... numbers)
otherwise you'd use an array or collection
int add(int[] numbers)
You can then of course have another method provide the value of these parameters:
add(someOtherMethod())
Varargs
Java has a built-in feature to denote a variable length of arguments. It is called varargs (documentation) (variable arguments) and it only works if the type stays the same. The syntax for a method is like this:
public int add(int... values)
Note the int... values which denotes varargs. A caller can now call the method like
add(null) // Passing null
add(values) // Passing an int[]
add() // No arguments
add(a) // One int
add(a, b) // Two ints
add(a, b, c) // Three ints
add(a, b, c, d) // Four ints
...
Note the three special cases null, int[] and empty.
What Java does is it will convert the arguments into an array. So inside the method values will be a regular int[]. You could thus implement the method like
public int add(int... values) {
int sum = 0;
for (int value : values) {
sum += value;
}
return sum;
}
If you, as a caller, want to pass the return value of a function you just need to make sure that it returns an array like int[]. So the following would work:
public int[] valueProvider() {
int[] values = ...
return values;
}
and then call it like
int sum = add(valueProvider());
Collection, Iterable and Stream
Besides that, if you don't want to use varargs or arrays, you can use Collections (documentation). A collection may be a List or a Set and so on. For example you could declare
public int add(Collection<Integer> values)
and feed it like
Collection<Integer> values = new ArrayList<>();
values.add(1);
values.add(2);
int sum = add(values);
An Iterable<Integer>, in contrast to Collection<Integer> would even be more flexible.
Using a Stream (documentation) would also work like a charm and is probably one of the most flexible variants since the source of a stream could be anything and nearly anything of the standard library supports a stream representation.
Changing type
Now note that what you searched for in the beginning, a method that is able to feed arbitrary arguments, is not possible in Java.
The main problem is that the types may change, so you may have a method like
public void doSomething(int first, String second, File third)
and you won't be able to feed the method with varargs, Collections or any of the presented methods.
In that case you will need a wrapper class like
public class DoSomethingArguments {
private int mFirst;
private String mSecond;
private File mThird;
public DoSomethingArguments(int first; String second, File third) {
this.mFirst = first;
this.mSecond = second;
this.mThird = third;
}
// Some getters
}
(or a generic tuple class, a triple in this case)
But then you would need to change the method to
public void doSomething(DoSomethingArguments arguments)
what is probably not what you wanted since you probably intended to not change the signature of doSomething.
But unfortunately there is no way to feed a method like this in such a way.
There is nothing that works the way you wish for at compile time. As the other answers are pointing out, there are varargs. But that is just syntactical sugar. That is just the compiler implicitly creating an array of a certain type for you.
But beyond that, there is reflection. Reflection allows you to dynamically inspect classes and methods at *runtime.
In other words: you can do something like
Object whatever = ...
Class<?> someClass = whatever.getClass();
And now you can ask someClass about the methods it has. And which parameters they need.
But as said: all of that is runtime only. And it the reflection APIs are very easy to get wrong. And you only find out at runtime, when some exception is thrown.
There is not direct way to pass multiple values in the way you want. But you can use a indirect way to pass a group of values of different type. I can think of two ways but their can be more.
Firs - Use a map, just insert the values you want to pass in the collection and pass the collection to the second method.
Second - Create a bean (Java POJO) to pass as parameter to the consuming method.
A small sample code.
class Sample{
private int a;
private String b;
private int c;
Sample(int a,String b,int c){
this.a = a;
this.b = b;
this.c = c;
}
public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
public String getB() {
return b;
}
public void setB(String b) {
this.b = b;
}
public int getC() {
return c;
}
public void setC(int c) {
this.c = c;
}
}
public class PassingExample {
public void consumerofInputs (Map<Integer, Object> input)/*(int a, String b, int c)*/{
System.out.println("I use three different inputs : int, string and int");
for (Map.Entry<Integer, Object> entry : input.entrySet()) {
System.out.println("Key : " + entry.getKey() + " Value : " + entry.getValue());
}
}
public Map producingInput() {
Map<Integer, Object> input = new HashMap<Integer, Object>();
input.put(1, 10);
input.put(2, "input");
input.put(3, 89);
return input;
}
public Sample createClassAsInput(){
Sample input = new Sample(10,"class-input",30);
return input;
}
public void useSampleAsInput(Sample input){
System.out.println("\nUsing Class as input \nInt::"+input.getA()+"\nString::"+input.getB()+"\nInt::"+input.getC());
}
public static void main(String[] args) {
PassingExample example = new PassingExample();
example.consumerofInputs(example.producingInput());
example.useSampleAsInput(example.createClassAsInput());
}
}

Java printing inherited objects with a println method

I'm taking those first steps from python to java and here is my first of many Java questions do doubt.
When printing via a shortened print method, I'm running into a problem with the return value from a inherited class. I'm sure it's something simple about Java I don't get yet. I'm also trying to convert any integers the println method receives to a string with .tostring(), but I'm not sure if that is correct.
class Inheritance {
private static void println (Object line){
System.out.println(line.toString());
}
static class A {
public int multiply(int a, int b){
int val = a*b;
return val;
}
}
static class B extends A {
public int multiply(int a, int b) {
int val = a * b * 5;
return val;
}
}
public static void main(String[] args) {
B b_class = new B();
b_class.multiply(3,4);
println(b_class);
println("Hello World");
}
}
The output is as follows:
Inheritance$B#74a14482
Hello World
You can just use the method inside println
public static void main(String[] args) {
B b_class = new B();
println(Integer.ToString(b_class.multiply(3,4)));
println("Hello World");
}
For Java toString method default it will
returns a string consisting of the name of the class of which the object is an instance, the at-sign character `#', and the unsigned hexadecimal representation of the hash code of the object. In other words, this method returns a string equal to the value of:
getClass().getName() + '#' + Integer.toHexString(hashCode())
https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#toString()
so when you println b_class it will print: Inheritance$B#74a14482.
For your println (Object line) it's receiving Reference type(Object) to println, but as multiply method it's return a primitive type(int), it's not an object, you need to convert it to an Object for println method, as #StanteyS's answer, use Integer.toString can convert int to String.
What's the difference between primitive and reference types?
When you are executing println(b_class); implicitly it calls toString method of same class, which is inherited from Object class.
You need to override toString method to display correct output.
static class B extends A {
int val=0;
public int multiply(int a, int b) {
val = a * b * 5;
return val;
}
public String toString(){
return String.valueOf(val);
}
}
Now, println(b_class); will work as per your expectation.

Is there a multiplication analogue to Integer::sum?

Since Java 8, the Integer class has a static sum method that adds two integers:
public static int sum(int a, int b) {
return a + b;
}
I can pass this method to higher-order functions via Integer::sum which I find more readable than (a, b) -> a + b.
Is there a similar static method for multiplication, so I don't have to write (a, b) -> a * b? I couldn't find one in the Integer class.
You can make it yourself:
public static int mult(int a, int b) {
return a * b;
}
This might seem obvious in retrospect but outside of that I don't believe there's actually a jdk-included method which multiplies for you, except for Math#multiplyExact (Math::multiplyExact), though this might be more than you need.
Math::multiplyExact
static int multiplyExact(int x, int y)
Returns the product of the arguments, throwing an exception if the result overflows an int.

Java type that holds two primitives of any primitive type

I want to store two primitive values (and I'm including String as a primitive here) inside a field. For example, I may want to store a String and an int as below:
("hello", 42)
So if the type I'm looking for is X, I'd like to be able to declare a field
private X myX = new X("hello", 42);
or some other incantation that gives me the same result.
I'm trying to figure out what type that field has to be. It has to accept any Java primitive type and String so it could be a String + int or String + float... actually any combination of primitive (+ String) types. Essentially, to borrow a concept from functional languages, I just want a tuple that's restricted to primitives. But Java doesn't have that.
Since they are primitives, generics don't work very well. And I'm not sure how I feel about boxing/unboxing.
What is the best data type/structure I can use in Java to do it?
Don't think that there is a way to do it with built-in Java libraries. However one could write Tuple class identical to Tuple2 class in Scala language like this:
public class Tuple<K, V> {
private K first;
private V second;
// create tuple only with static method "of"
private Tuple(K first, V second) {
this.first = first;
this.second = second;
}
public static <K, V> Tuple<K, V> of(K a, V b) {
return new Tuple<K, V>(a, b);
}
public Tuple<V, K> swap() {
return new Tuple<V, K>(second, first);
}
public K getFirst() {
return this.first;
}
public V getSecond() {
return this.second;
}
#Override
public String toString() {
return "(" + first.toString() + "," + second.toString() + ")";
}
public static void main(String[] args) {
Tuple myTuple = Tuple.of("hello", 2);
System.out.println("toString: "+myTuple);
System.out.println("First: "+myTuple.getFirst());
System.out.println("Swap: "+ myTuple.swap());
}
}
Output:
toString: (hello,2)
First: hello
Swap: (2,hello)
If you really want to store the values as one primitive type, you have to 'encode' them.
For example:
String field = "hello;42";
String[] values = field.split(";");
int intValue = Integer.parseInt(values[1]);
Since you're working with only primitives (and String) it seems that you'd like to avoid auto-boxing and unboxing if possible. That means you can't use generics. (Primitive types can't be used as type arguments.) It also seems as though you'd like to avoid unnecessary promotion (e.g. if you stored floats as doubles you'd preserve the original value, but lose the fact that it's actually a float).
A rather elaborate solution would be to create a set of PrimitivePair classes, one for each combination of primitive types that you want to store, along with a factory class for constructing them easily. For example, you might have the following three classes to store various pairs of primitives:
package primitivepair;
public class PrimitivePairStringInt
{
final String s;
final int i;
PrimitivePairStringInt(final String s, final int i)
{
this.s = s;
this.i = i;
}
public String getFirstValue()
{
return s;
}
public int getSecondValue()
{
return i;
}
}
package primitivepair;
public class PrimitivePairFloatDouble
{
final float f;
final double d;
PrimitivePairFloatDouble(final float f, final double d)
{
this.f = f;
this.d = d;
}
public float getFirstValue()
{
return f;
}
public double getSecondValue()
{
return d;
}
}
package primitivepair;
public class PrimitivePairCharByte
{
final char c;
final byte b;
PrimitivePairCharByte(final char c, final byte b)
{
this.c = c;
this.b = b;
}
public char getFirstValue()
{
return c;
}
public byte getSecondValue()
{
return b;
}
}
They would be created by the following factory class:
package primitivepair;
public class PrimitivePairFactory
{
public static PrimitivePairCharByte createPrimitivePair(final char c, final byte b)
{
return new PrimitivePairCharByte(c, b);
}
public static PrimitivePairFloatDouble createPrimitivePair(final float f, final double d)
{
return new PrimitivePairFloatDouble(f, d);
}
public static PrimitivePairStringInt createPrimitivePair(final String s, final int i)
{
return new PrimitivePairStringInt(s, i);
}
}
You can of course add more classes and factory methods for other combinations.
I wanted to make an abstract PrimitivePair class that would have the creation methods and method declarations for the getFirstValue() and getSecondValue() methods, but that would have required that return type covariance works for primitives, and I don't believe it does.
Java does not have a built-in Tuple type.
You might use the standard Map.Entry<K,V> but I would personally suggest Apache Commons Lang3's Tuple type if possible.

Categories