I am exploring both scala and Java 1.8 but unable to find equivalent code in with java 1.8 lambda expressions.
Scala code:
object Ex1 extends App {
def single(x:Int):Int =x
def square(x:Int):Int = x * x
def cube(x:Int):Int = x*x*x
def sum(f:Int=>Int,a:Int,b:Int):Int=if (a>b) 0 else f(a) + sum(f,a+1,b)
def sumOfIntegers(a:Int,b:Int)=sum(single,a,b)
def sumOfSquares(a:Int,b:Int)=sum(square,a,b);
def sumOfCubes(a:Int,b:Int)=sum(cube,a,b);
println(sumOfIntegers(1,4));
println(sumOfSquares(1,4));
println(sumOfCubes(1,4));
}
output:
10
30
100
java:
public class Test1{
public int single(int x){
return x;
}
public int square(int x){
return x * x;
}
public int cube(int x){
return x * x * x;
}
// what's next? How to implement sum() method as shown in Scala?
// Stuck in definition of this method, Stirng s should be function type.
public int sum( Sring s , int a, int b){
// what will go here?
}
public int sumOfIntegers(int a, int b){
return sum("single<Function> how to pass?",a,b);
}
public int sumOfSquares(int a, int b){
return sum("square<Function> how to pass?",a,b);
}
public int sumOfCubes(int a, int b){
return sum("cube<Function> how to pass?",a.b);
}
}
Is it possible to achieve the same with JDK 1.8?
You are going to need to define the methods that you are going to use. The only one that comes with Java is the Function<X,Y> which (with Integer) can be used for single, square and cube and BiFunction<T,Y, R> which can be used for the three sumOfs.
interface Sum {
Integer apply(Function<Integer, Integer> func, int start, int end);
}
The single, square and cube could be either methods in the class (see cube or inline (see the other two). They are Fuctions. This function can then be passed to other methods and called with variableName.apply.
class Test
{
private static Integer sum(Function<Integer, Integer> func, int a, int b) {
if (a>b)
return 0;
else return func.apply(a) + sum(func,a+1,b);
}
private static Integer cube(Integer a) {
return a * a * a;
}
public static void main (String[] args) throws java.lang.Exception
{
Function<Integer,Integer> single = a -> a;
Function<Integer,Integer> square = a -> a * a;
Function<Integer,Integer> cube = Test::cube;
// You can not do the sum in-line without pain due to its recursive nature.
Sum sum = Test::sum;
BiFunction<Integer, Integer, Integer> sumOfIntegers = (a, b) -> sum.apply(single, a, b);
BiFunction<Integer, Integer, Integer> sumOfSquares = (a, b) -> sum(square, a, b); // You could just use the static method directly.
BiFunction<Integer, Integer, Integer> sumOfCubes = (a, b) -> sum(cube, a, b);
System.out.println(sumOfIntegers.apply(1,4));
System.out.println(sumOfSquares.apply(1,4));
System.out.println(sumOfCubes.apply(1,4));
}
}
Yes, it is possible:
public Integer sumSingle(Integer a) { return a; }
public int sum(Function<Integer, Integer> f, int a, int b)
{
... : f.apply(a+1); // or whatever
}
public int sumOfIntegers(int a, int b)
{
return sum(Test1::single, a, b);
}
The construct Class::method creates a Function object from the method. Or if you don't need to reuse it, you can directly pass an argument instead: (Integer a) -> a*a* ...
Function<Integer, Integer> single = x -> x;
Function<Integer, Integer> square = x -> x*x;
public int sum( Function<Integer, Integer> s , int a, int b){
if (a>b){
return 0;
} else {
s.apply(a) + sum(s,a+1,b)
}
}
In Java 8 you can use any functional interface, i.e. an interface with exactly one non-static method without a default implementation, in place of Scala's Function<N> types. There are quite a few such interfaces in the java.util.function package, for single-argument and two-argument functions; in particular for functions which take and return int you should use IntUnaryOperator, already mentioned in other people's comments. If you have more than two arguments, or two arguments of different types, define your own interface with one method. E.g. for functions of 3 arguments which take int, long and long and return a non-primitive:
interface Fun3ILLO<T> {
public T apply(int arg1, long arg2, long arg3);
}
(obviously you can choose the interface and method name you want).
Related
I was trying to convert a lambda expression into method reference, but I failed to do so.
can anybody help me with this?
The lambda expression takes 2 int parameters adds it and return the result.
public class Addition {
public static void main(String[] args) {
int a = 10;
int b = 20;
A ref = (int c, int d) -> c + d;
System.out.println(ref.add(a, b));
}
}
Based on the signature of the method implemented by your lambda expression, you can replace it with:
A ref = Integer::sum;
Since that sum method accepts two int arguments and returns their int sum:
public static int sum(int a, int b) {
return a + b;
}
This question already has answers here:
Java Pass Method as Parameter
(17 answers)
How to pass a function as a parameter in Java? [duplicate]
(8 answers)
Closed 3 years ago.
I have a class with bunch of methods. In another class, I need to write a method, that handles the input values. To that method, I want to pass the method of the class that I want to call. How can we do that with Java after 1.8?
There are similar questions already, but those usually assume that we can use an interface with a single method, therefore can use lambda expressions, etc.
class MyClass {
public Object myToString(String a) {
return new String(a);
}
public Object myToString(String a, String b) {
return new String(a + ", " + b);
}
public Object mySum(int a) {
return new Integer(a);
}
public Object mySum(int a, int b) {
return new Integer(a + b);
}
}
class Test {
public Object handleInputs(MyClass myClass, MethodAsParameter theMethod, List<Object> inputs) {
if (type of inputs are Strings) {
myClass.myToString(inputs.get(0));
} else if (.....) {
myClass.mySum(inputs.get(0));
}
}
}
Since Java 8 you can use method reference. Method references can be assigned to Function<A, B> functional interface variables and their subclasses.
For example, method with such signature:
class Test {
public static int DoSomething(String s) {...}
}
can be assigned to a Function<String, Integer> variable like:
Function<String, Integer> method = Test::DoSomething;
and then called:
int result = method.apply("Hello!");
So with small improvements in your code, this is the way you can use your methods as method references and passed to other function as parameters.
class MyClass {
public static String myToString(String a, String b) {
return a + ", " + b;
}
//notice the boxing in here
public static int mySum(int a, int b) {
return a + b;
}
//not kind of an revolutionary function, just for demonstration
public static<T> T Invoke(BinaryOperator<T> bo, T o1, T o2) {
return bo.apply(o1, o2);
}
public static void main(String[] args) {
int sum = Invoke(MyClass::mySum, 10, 20);
String str = Invoke(MyClass::myToString, "a", "b");
System.out.println(sum);
System.out.println(str);
}
}
I think something like this is as far as you would get:
import java.util.List;
import java.util.Arrays;
import java.util.function.Function;
import java.util.function.BiFunction;
class MyClass {
public Object myToString(String a) {
return new String(a);
}
public Object myToString(String a, String b) {
return new String(a + ", " + b);
}
public Object mySum(int a) {
return Integer.valueOf(a);
}
public Object mySum(int a, int b) {
return Integer.valueOf(a + b);
}
}
public class MethodParams {
public static Object handleInputs(Function<Object,Object> method, List<Object> inputs) {
return method.apply(inputs.get(0));
}
public static Object handleInputs(BiFunction<Object,Object,Object> method, List<Object> inputs) {
return method.apply(inputs.get(0), inputs.get(1));
}
public static void main(String args[]) {
MyClass mc = new MyClass();
String str = (String)handleInputs((a) -> mc.myToString((String)a), Arrays.asList("string"));
System.out.println(str); // string
Integer sum = (Integer)handleInputs((a) -> mc.mySum((int)a), Arrays.asList(1));
System.out.println(sum); // 1
Integer sum2 = (Integer)handleInputs((a,b) -> mc.mySum((int)a, (int)b), Arrays.asList(1, 2));
System.out.println(sum2); // 3
}
}
Not very nice, but at least you have some leeway as to which method you want to use. Code as demonstrated here has lots of casts due to using Objects - using generic types as demonstrated by t2dohx is better way of doing this, but even further from your question.
Here is a simple example:
public class TestMain {
public static void main(String [] args) {
Long a = 15L, b = 20L;
Long sum = combineTwoNumbers(a, b, (p1, p2) -> p1 + p2);
Long product = combineTwoNumbers(a, b, (p1, p2) -> p1 * p2);
System.out.println("Sum is " + sum);
System.out.println("Product is " + product);
}
public static Long combineTwoNumbers(Long a, Long b, BiFunction <Long, Long, Long> combiner) {
return combiner.apply(a, b);
}
}
Here, the functional parameter is BiFunction, which takes two parameters in input and returns an output. Specifically, it takes two long numbers and produces a third one as a result. The name of the method is kept generic so that it can cover more instances of different functions that may take place. In our example we are passing a sum and a product function as you can see.
This is one of the practice questions of a test:
Write a method which accepts two integer values as input parameters and returns the boolean result true if the sum of the inputs is greater than or equal to 10 (and falseotherwise)
My answer is below but I don't think it looks correct. Can anyone give me a pointer?
public class Bruh{
public static void main (String [] arg){
int a;
int b;
boolean sum = true;
if ( a+b > 10)
System.out.println ("yo");
else{
sum = false;
}
}
}
You only wrote some code in the main method but you did not create one.
In order to do that you need to actually create a method in your Bruh class like:
public static boolean isSumGreaterThan9(int a, int b){
return (a + b) > 9;
}
Than call it from the main method:
public static void main (String [] arg){
int a = 4; // or whatever
int b = 7; // or whatever
System.out.println(isSumGreaterThan9(a, b));
}
You need to put your logic into a method and change your comparison to >= as per the requirement:
public static boolean isSumGreaterThanOrEqualToTen(int a, int b) {
return (a + b) >= 10;
}
Can you help me find my error?
I'm trying to use these two methods here but my output is not working.
class Nine {
public static void Nine(String[] args) {
int x,y,z;
y = 3;
x = 7;
z = addEm(a, b);
System.out.println("answer= " +x);
}
public static addEm (double a, double b){
int c;
c = a+b;
}
}
Actually there are a lot of error in your code:
z=addEm(a, b);
here a and b are meaningless, you should use z=addEm(y,x); (if your intent is to sum three with seven)
System.out.println("answer= " +x);
I guess that you want to show the the results of the sum, therefore you should print z (and not x), so you should substitute with System.out.println("answer= " +z);
public static addEm (double a, double b) {
Here you missed the return type, and you need to consider also the type of parameters a and b. Since y,x and z are int, it is better if also a and b are int, and therefore specify also the return type as int:
public static int addEm (int a, int b) {
Or you can declare everything (y,x,z,a,b and return type) as a double: the important here is that they should be all of the same type. Moreover you miss also the return statement of the function addEm, that summarizing becomes:
public static int addEm (int a, int b)
{
int c;
c=a+b;
return c;
}
And finally also the function
public static void Nine(String[] args)
it is not right named for an entry point: its names should be main.
So in conclusion, if you apply all the fix (by modifying as less as possible your original code) a code that compile, run and works following some 'logic' is:
class Nine {
public static void main(String[] args) {
int x, y, z;
y = 3;
x = 7;
z = addEm(y, x);
System.out.println("answer= " + z);
}
public static int addEm(int a, int b) {
int c;
c = a + b;
return (c);
}
}
Man, this is a very basic java lesson:
every prog need an entry point, which is in java:
public static void main(String args[]){}
And then your code will execute.
You're passing arguments a and b to addEm, but those variables aren't initialized. I'm expecting you wanted to pass x and y instead.
class Nine
{
public static void Nine(String[] args)
{
int x,y,z;
y=3;
x=7;
z=addEm(x, y);
System.out.println("answer= " +x);
}
public static addEm (double a, double b)
{
int c;
c=a+b;
}
}
Your code will not work because your addEm method does not have any return type. In addition, the method you wrote takes Double params but while using you are trying to pass int to it. You also do not have any main method. I am assuming you misspelled or misunderstood the main method so below is the code which should work
class Nine
{
public static void Main(String[] args)
{
int x,y,z;
y=3;
x=7;
z=addEm(x, y);
System.out.println("answer= " + x);
}
public static int addEm (int a, int b)
{
int c;
c=a+b;
return c;
}
}
Essentially, I'd like to do the following as a one-liner:
int sum = initialValue;
for (int n : collectionOfInts) {
sum += n;
}
return sum;
I see that there's http://functionaljava.org/examples/1.5/#Array.foldLeft, but I'd rather not have to copy the collection.
I see that there's http://functionaljava.org/examples/1.5/#Array.foldLeft, but I'd rather not have to copy the collection.
If you use the foldLeft from IterableW instead of Array, you won't have to copy anything.
Sorry, it still doesn't exist in Java 7. You'll have to wait for Java 8, where Closures shall be implemented.
In the meantime, you can use FunctionalJava, Guava, or a JVM-compatible, closure-enabled language such as Groovy.
Just for fun - here's how to do it without an external library:
return fold(collectionOfInts, 0, ADD);
Oh, and here's the rest :)
static <X, Y> X fold(final Iterable<? extends Y> gen, final X initial, final Function2<? super X, ? super Y, ? extends X> function) {
final Iterator<? extends Y> it = gen.iterator();
if (!it.hasNext()) {
return initial;
}
X acc = initial;
while (it.hasNext()) {
acc = function.apply(acc, it.next());
}
return acc;
}
static final Function2<Integer, Integer, Integer> ADD = new Function2<Integer, Integer, Integer>() {
#Override
public Integer apply(Integer a, Integer b) {
return a + b;
}
};
interface Function2<A, B, C> {
C apply(A a, B b);
}