public class TestSupplier {
Optional<Integer> opt1;
public static void main(String[] args) {
// TODO Auto-generated method stub
TestSupplier ts1 = new TestSupplier();
ts1.opt1 = ts1.average(100,20,30,80);
Consumer<Integer> cns1 = (x) -> x += 3;
ts1.opt1.ifPresent(cns1);
System.out.println(ts1.opt1.get());
}
private Optional<Integer> average(int... n1) {
if (n1.length == 0) return Optional.empty();
int sum = 0;
for(int score: n1) sum += score;
return Optional.of(sum/n1.length);
}
}
when I run the code the result is 57 (that is the correct result of 100, 20, 30, 80 average) but I create a Consumer that should increment the result by 3... but it seems to not work.
Can someone help me?
The Consumer action is actually being run but the body you provided modifies only a local instance which eventually gets lost. The ifPresent() method should be used for performing side-effects(actions) only.
If you want to perform a calculation on a value held by an Optional instance, use map() instead.
ts1.opt1
.map(x -> x + 3).orElseThrow(...)
Remember to be careful when using get() on an Optional instance. Before you decide to use it, have a look at orElse, orElseGet, and orElseThrow.
Consumer<Integer> cns1 = new Consumer<Integer>() {
public #Override void accept(Integer x) {
// x is a local variable
x += 3; // unboxing, adding, boxing
// the local variable has been changed
}
};
It is that case when turning a lambda into an anonymous class perfectly makes this all clear to understand.
The best possible way here is
ts1.opt1.map(x -> x + 3).ifPresent(System.out::println);
You could use an instance of a mutable class (e.g. the AtomicInteger class):
Consumer<AtomicInteger> cns1 = x -> x.addAndGet(3);
which changes its state after accepting the Consumer<AtomicInteger> (although it is not recommended, look at #pivovarit's answer).
Furthermore, the line
IntStream.of(100, 20, 30, 80).average().ifPresent(System.out::println);
might replace all your routine work.
Related
I have a method which uses Deque. In 1 place, sometimes I want to Deque.pullFirst() and sometimes Deque.pullLast(). It should depend on one of the arguments passed to the method. How do this with Java 8?
This is my try with Callable I know that it doesn't work but now you can understand what I want to achieve:
public class AppMain {
public void iterateThroughQueue(Callable callable) { // error
Deque<Integer> deq = new ArrayDeque<>();
deq.add(1);
deq.add(2);
deq.add(3);
for (int i = 0; i < 3; i++) {
System.out.println(callable.apply(deq)); // error!
}
System.out.println("size after iteration = " + deq.size());
}
public static void main(String[] args) {
AppMain.iterateThroughQueue(Deque::pollFirst); // error!
}
}
Method references are either:
Consumer<T>, which means they take a parameter and return nothing. For example System.out::println is a Consumer<String>.
Producer<T>, which means they take no parameter and return something. For example UUID::randomUUID is a Producer<UUID>.
Function<T,Z>, which means they take a parameter of type T (can be the instance on which to apply the method) and return a result of type Z, in your case Deque::pollFirst take is a Function<Deque<Integer>, Integer>. Another example is deq::add where deq is an instance of Deque<Integer> which would be a Function<Integer, Boolean> .
So you should be using Function<Deque<Integer>, Integer> instead of Callable which is for something completely different. Also iterateThroughQueue(...) need to be static.
Callable will not work here, but Function will.
You could try instead this:
public static void iterateThroughQueue(Function<Deque<Integer>, Integer> function) {
Deque<Integer> deq = new ArrayDeque<>();
deq.add(1);
deq.add(2);
deq.add(3);
for (int i = 0; i < 3; i++) {
System.out.println(function.apply(deq));
}
System.out.println("size after iteration = " + deq.size());
}
public static void main(String[] args) {
iterateThroughQueue(Deque::pollFirst);
}
This prints:
1
2
3
size after iteration = 0
Is there any scenario in which AtomicInteger.accumulateAndGet() can't be replaced with AtomicInteger.updateAndGet(), or is it just a convenience for method references?
Here's a simple example where I don't see any functional difference:
AtomicInteger i = new AtomicInteger();
i.accumulateAndGet(5, Math::max);
i.updateAndGet(x -> Math.max(x, 5));
Obviously, the same goes for getAndUpdate() and getAndAccumulate().
When in doubt, you may look into implementation:
public final int accumulateAndGet(int x,
IntBinaryOperator accumulatorFunction) {
int prev, next;
do {
prev = get();
next = accumulatorFunction.applyAsInt(prev, x);
} while (!compareAndSet(prev, next));
return next;
}
public final int updateAndGet(IntUnaryOperator updateFunction) {
int prev, next;
do {
prev = get();
next = updateFunction.applyAsInt(prev);
} while (!compareAndSet(prev, next));
return next;
}
They differ only in single line and obviously accumulateAndGet could be expressed easily via updateAndGet:
public final int accumulateAndGet(int x,
IntBinaryOperator accumulatorFunction) {
return updateAndGet(prev -> accumulatorFunction.applyAsInt(prev, x));
}
So updateAndGet is somewhat more basic operation and accumulateAndGet is a useful shortcut. Such shortcut might be especially helpful if your x is not effectively final:
int nextValue = 5;
if(something) nextValue = 6;
i.accumulateAndGet(nextValue, Math::max);
// i.updateAndGet(prev -> Math.max(prev, nextValue)); -- will not work
There are cases where an instance creation can be avoided by using accumulateAndGet.
This is not really a functional difference but it might be useful to know about.
Consider the following example:
void increment(int incValue, AtomicInteger i) {
// The lambda is closed over incValue. Because of this the created
// IntUnaryOperator will have a field which contains incValue.
// Because of this a new instance must be allocated on every call
// to the increment method.
i.updateAndGet(value -> incValue + value);
// The lambda is not closed over anything. The same
// IntBinaryOperator instance can be used on every call to the
// increment method.
//
// It can be cached in a field, or maybe the optimizer is able
// to reuse it automatically.
IntBinaryOperator accumulatorFunction =
(incValueParam, value) -> incValueParam + value;
i.accumulateAndGet(incValue, accumulatorFunction);
}
Instance creations are generally not expensive but can be important to get rid of in short operations that are used very frequently in performance sensitive locations.
More information about when lambda instances are reused can be found in this answer.
So I understand how to use a recursive method that has some other return type other than void. Typically I would call the same method again in the same method( inside the recursive case), while decremented or increment some value in the call to reach the base case. Then at some point the base case is reached and the problem is solved, so it starts returning the value from every call. Along those lines.
BUT
What if the method has the return type void, so you can't call the method as it won't/can't return anything? I'm trying to write a sentence backwards, which I've solved both with a for loop and a resucrive method that can return a string value, but I'm not sure how to approach it if it's void which is what the assignment is asking for.
Edit: I should also mention the sentence can only be passed in the parameter
Thank you everyone for the information and the help!
Recursion doesn't work only with methods/functions that return values. Recursion means only that the method/function calls itself.
You must guarantee that there is at least one stop condition but this does not require the function to return a value. This is commonly achieved by incrementally changing one or more arguments that you pass each time the function recursively calls itself. When that/those arguments satisfy a certain condition your function no longer calls itself and all pending operations are solved.
I am not fully aware of the task you are trying to do but here is an example of a recursive function that writes a string backwards. I use PSEUDO-functions with names that hopefully are self-explanatory.
public void writeBackwards(String str) {
// This is the negation of the stop condition, so the stop condition
// is when the string is empty, in which case this function will do
// nothing:
if (!str.isEmpty()) {
char firstCharacter = str.getFirstCharacter();
str = str.removeFirstCharacter();
writeBackwards(str); // the recursive call
// The following operation will be pending, waiting for the
// recursive call to be resolved first:
writeCharacter(firstCharacter);
}
}
You can use any mutable Object as a parameter of the recursive function to store the result. For example, the backwards-sentence problem you mentioned could be written as:
public void stringReverse(String s, int index, StringBuilder sb) {
if (index < 0)
return;
sb.append(s.charAt(index));
stringReverse(s, index - 1, sb);
}
And called like this
StringBuilder sb = new StringBuilder();
stringReverse(mySentence, mySentence.length() - 1, sb);
Just like in C++ you can pass in pointers, here in Java you can simply pass in a class object to your function to hold the value generated from the recursive calls of the function. A simple example reflecting your question to compute fibonacci number is following.
public class ComputeFibonacci {
static class Fibonacci {
public int ith;
public int value;
Fibonacci(int a, int b) {
ith = a;
value = b;
}
}
private static void fibonacci(Fibonacci result) {
if (result.ith == 1 || result.ith == 2) {
result.value = 1;
} else {
Fibonacci left = new Fibonacci(result.ith - 1, 0);
Fibonacci right = new Fibonacci(result.ith - 2, 0);
fibonacci(left);
fibonacci(right);
result.value = left.value + right.value;
}
}
public static void main(String[] args) {
// Here we compute the 10th fibonacci number
Fibonacci f = new Fibonacci(10, 0);
fibonacci(f);
System.out.println("The result is " + f.value);
}
}
Good luck.
Is it a good practice to use properties as local variable. In cases where there are many methods which uses some variables, In each method the variable value changes. This avoids many times creating new variables and the code increases. Any suggestion?
private void method1(){
int totalLength = length1 + 10;
int totalBreath = (breath1 + breath2) + 20;
int size = (totalLength * totalLength);
System.out.println(size);
}
private void method2(){
int totalLength = length1 + 20;
int totalBreath = (breath1 + breath2) + 30;
int size = (totalLength * totalLength);
System.out.println(size);
}
private void method3(){
int totalLength = length1 + 60;
int totalBreath = (breath1 + breath2) + 10;
int size = (totalLength * totalLength);
System.out.println(size);
}
As you can see, totalLength, totalBreath, size is repeated in every method. Can i make them as fields of the class? So, i need not declare it in every method.
private void method1(){
totalLength = length1 + 10;
totalBreath = (breath1 + breath2) + 20;
size = (totalLength * totalLength);
System.out.println(size);
}
I read your question as, "When should a local variable be promoted to be a field of the class?"
The best answer is "it depends" but then again, its accuracy is quickly eclipsed by its lack of usefullness.
Fields should have a relationship to the class itself, as in is the field an attribute of the class? I include an example below to illustrate the syntax difference, but I agree with this post that it should be avoided if it pollutes the meaning of the class.
Usually you only need to have a field when you need the value of the field to be maintained between calls to different methods for a given instance of the class, with the option of making it static when the value should be maintained between method calls for all instances of the class. It will depend on several factors like shop convensions, performance goals, existing codebase, etc. so there is no single right answer without specific code. This question seems to include similar points. If you find yourself using the approach below, you might consider other approaches like refactor the behavior into a help class.
Another question asks the same question but from the perspective of a programming student.
Examples:
public class VariableScope {
int field1 = 3;
void foo() {
int a = 2;
// variable passing in width
bar1(1);
bar2(1);
// variable passing in depth
bar3(a);
// uses a field to reduce variable passing
baz1();
baz2();
}
void bar1(int param) {
System.out.println("param=" + param);
}
void bar2(int param) {
System.out.println("param=" + param);
}
void bar3(int param)
{
System.out.println("Passing param to bar4");
bar4(param);
}
void bar4(int param){
System.out.println("param=" + param);
}
void baz1() {
System.out.print("field1=" + field1);
}
void baz2() {
System.out.print("field1=" + field1);
}
}
From what it sounds like, if you're using the variable for multiple methods you're should declare the variable as a global variable. But yes, If no other method needs that variable , and you don't want to be writing a bunch of return statements you can use local variables
I suppose you mean a field by property which usually has accessor and mutator (get,set-methods).
In common you should keep the scope of a variable as small as possible. An example if you use many for loops like:
for ( int i = 0 ; i < 10 ; i++ ) {
}
and replace this by
int i;
method1() {
for ( i = 0 ; i < 10 ; i++ ) {
// some code;
}
}
method2() {
for ( i = 0 ; i < 10 ; i++ ) {
// some code;
}
}
If one thread calls method1() and another one method2() you would face a race condititon.
You can easily introduce hard to find bugs in your code.
I assume you mean something like this:
Class foo() {
int x;
public bar() {
for(x = 0; x <100; ++x) ...
} }
No, it's not good practice.
One place where it can even be harmful is in the synchronization/concurrency/multi-threaded case: if you are working with class members, they are going to need be synchronized which will eat into performance. Otherwise you risk multiple threads overwriting the value of the field and that can lead to errors in your program (likely hard to debug).
Is it possible to retain information via a helper function with java, without using static variables.
For example,
public void foo(){
int v = 0;
fooHelper(2);
}
public void fooHelper(int depth){
v++;
fooHelper(depth-1)
}
Namely I want to update variable v without loosing the information for each recursive case, without having to access a variable outside the function.
Forget about all the answers that tell you to declare attributes, or to update mutable objects in each recursive call. In a true functional, recursive style you "retain" information by passing it as parameters and/or return types.
Let me illustrate with a simple example, let's say that you want to recursively calculate the sum of the elements in an int[]. Here, the state (the information that needs to be retained between recursive calls) is the current index in the array and the sum so far. Here's how to do it:
public int sum(int[] array) {
return sum(array, 0, 0);
}
private int sum(int[] array, int idx, int acc) {
if (idx == array.length)
return acc;
return sum(array, idx+1, acc+array[idx]);
}
Call it like this:
int[] array = {1, 2, 3};
System.out.println(sum(array));
As you can see, there's no need to declare (static or instance) attributes, and no need to pass and modify mutable objects (lists, maps) - I'm not even using local variables, because all the required information needed to solve the problem is present as method parameters.
In the code in your question the v variable is supposed to do what the acc parameter is doing in my answer, namely: modifying an accumulated value each time the recursion is called. In the end, you just need to return the accumulated value from the helper function (which must not have a void return type) and that's how you'll get the value in foo().
A variable declared in a scope (for example method) is accessible only in this scope (e.g. not in another method).
If the information is relevant for the method only, keep the variable in the method. If the information is relevant for the whole object / class state, keep it a class member (static/non static).
For example:
public void someRecursiveMethod(int num) {
while (num < 10) {
num++;
someRecursiveMethod(num);
System.out.println("Current num = " + num);
}
}
You can create a new class (yuck), or pass the variable as a parameter and return it in fooHelper.
Why not make it an instance variable(not necessarily static)...??
public class Recursive {
int v = 0;
public void foo(){
fooHelper(2);
System.out.println(v);
}
public void fooHelper(int depth){
v++;
if(depth-1!=0)//Added this because I was getting an StackOverflowError
fooHelper(depth-1);
}
public static void main(String[] args) {
Recursive r = new Recursive();
r.foo();
}
}
You could return a list or a similar data structure:
public List<Integer> fooHelper( int v, int depth ){
if( depth == 0 ) return new ArrayList();
v++;
List<Integer> result = fooHelper( v, depth-1 );
result.add( new Integer(v) );
return result;
}
Because the variable v is of primitive type, changes made to it will not be visible outside the function scope. You could declare the variable v inside a class, say State and pass the state object into the recursive function to get the required effect.
public void foo(){
State state = new State();
fooHelper(state, 2);
}
public void fooHelper(State state, int depth){
state.v++;
fooHelper(state, depth-1);
}
class State {
int v;
}
Hope it helps.
You can pass an object to store the update for each recursive call. Something like the one below.
public static void fooHelper(int depth, HashMap map){
map.put(depth, "Call " + depth);
if (depth > 0)
{
fooHelper(depth-1, map);
}
return;
}
I think this is called memoization. It looks like
class Fibonacci
{
public Map < Integer , Integer > memorized = new HashMap < > ( ) ;
public int fib ( int n )
{
if ( memoized . containsKey ( n ) )
{
return memoized . get ( n ) ;
}
else
{
int fib = // calculate recursively
memoized . put ( n , fib ) ;
return fib ;
}
}
}
You should be able to get decent (not optimal) performance out of this algorithm. The primary reason that the recursive fibonacci algorithm has horrible performance is b/c it is repeatedly calculating the same values. With recursion+memoization it never calculates any value more than once.
Thanks to #Aristide for pointing out the subtle difference between memorization and memoization.