6
\$\begingroup\$

Can I use #define fori(i,n) for(int i=0;i<=n;i++) in Java?

And of course, Java doesn't have precompiler so we cannot do that in java. So I thought we can do that fori method either using stream() or manually defining a method. But I thought instead of just traversing why can't I put the third parameter as lambda expression that operates.

Functional interface:

interface func
{
    int calculate(int a,int b);
}

Method implementation:

 int run(int[] array,int start,int end,func t)
 {
   int result =0;
   for(int i=start;i<=end;i++)
   {
     System.out.println(result);
     result = t.calculate(array[i], result);
    }
    return result;
  }

Usage:

public static void main(String[] args) 
{
        int[] array = {1,2,3,4,5,3,5,3,2,2,3,2,23,2};
        System.out.println(run(array, 0, 5, (a,b) -> a + b  ));
}

I would like a review on this code pattern. My major concern is that how much complicated lambda expression I can use here. Also, what is the future scope of this what could be done with this pattern?

\$\endgroup\$

2 Answers 2

6
\$\begingroup\$

The pattern you have implemented is basically a reduction or foldLeft method.
Compare it to the Stream#reduce method in Java, it is very similar.

To answer your question about the complexity of the lambda to put into the method: There is no limit. You can do everything you like in there. A lambda expression is nothing more than an implementation of the single-method interface you have created. And there is no limit on the complexity of a class implementing an interface.

Now for some real code review:

Use proper and understandable names and use built-in types

Your interface is simply named func. This probably means "function" but you don't have to save on characters, Java is already quite verbose.
What you have, is a special kind of BiFunction or more precisely, BinaryOperator. Now I know that generics don't allow you to specify primitive types for the generic arguments, but your func interface is not necessary and can be replaced by a BinaryOperator<Integer>.

Your run method has a very generic name. Sure, there is code that is run, but it doesn't explain, what this method does.
It would be more precise to call your method reduce or foldLeft or something similar, that explains in the name, what this method does.

Make your method do one thing

Currently your method calculates a result and, in addition to that, prints the value of result for every iteration. What if you or someone who uses your method does not want to have every single intermediate result printed to them?

If you want to print the intermediate values, do so in your lambda.

You wanted to think about the future

Your method currently only works with primitive integer arrays. Nothing stops you from making it work with generic types or even lists.
And if you go that far, you'll probably use streams anyway.

\$\endgroup\$
9
  • \$\begingroup\$ really helpful. I got your point. what should I do to define a method that supports various lambda expressions what we use in streams? \$\endgroup\$ Sep 18, 2019 at 12:37
  • \$\begingroup\$ What exactly do you mean with "various lambda expressions"? You can use any expression that satisfies the interface (ie. takes two integers as input and returns one integer). You can't really chain the expressions one after another because a reduce operation is terminal and returns exactly one value. \$\endgroup\$
    – GiantTree
    Sep 18, 2019 at 13:06
  • \$\begingroup\$ by Various I mean arithmetic operations . \$\endgroup\$ Sep 18, 2019 at 15:24
  • 1
    \$\begingroup\$ Ah, yeah, you can do anything in the lambda expression. There are no limits. \$\endgroup\$
    – GiantTree
    Sep 18, 2019 at 16:25
  • \$\begingroup\$ Can I delete Array elements with lambda ? Im sure that won’t be as like reduce method \$\endgroup\$ Sep 18, 2019 at 16:30
4
\$\begingroup\$

Most is already said by GiantTree, so only one additional remark: after replacing func with BinaryOperator (or in this case IntBinaryOperator) and the calculation with reduce, the only thing your run method really does is an array lookup.

You can solve this directly with the existing standard library - the following is equivalent to your code:

IntStream.rangeClosed(0, 5).map(i -> array[i]).reduce(0, (a, b) -> a + b);

My advice: don't reinvent the wheel, get a good grip on the basic libraries instead.

\$\endgroup\$
1
  • \$\begingroup\$ I know IntStream and reduce but It doesn't allow me to modify the underlying array. But In my pattern, I might modify the original array elements. \$\endgroup\$ Oct 3, 2019 at 14:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.