java 8 local variable in stream.foreach [duplicate] - java

This question already has answers here:
Variable used in lambda expression should be final or effectively final
(9 answers)
Closed 4 years ago.
I would like to use local variables in lambda functions but I get error:
Please see the 1. and 2. points in the code.
class Foo {
int d = 0; // 1. It compiles, but ugly, 2. doesnt compile
public void findMax(List<List<Route>> routeLists) {
int d = 0; // 2.Error : Local variable dd defined in an enclosing scope must be final or effectively final
routeLists.forEach(e-> {
e.forEach(ee -> {
d+=ee.getDistance();
});
});
... doing some other operation with d
}
}
How can I use them whitout setting them as global variables ?

forEach is the wrong tool for the job.
int d =
routeLists.stream() // Makes a Stream<List<Route>>
.flatMap(Collection::stream) // Makes a Stream<Route>
.mapToInt(Route::getDistance) // Makes an IntStream of distances
.sum();
Or just use nested for loops:
int d = 0;
for (List<Route> rs : routeLists) {
for (Route r : rs) {
d += r.getDistance();
}
}

You can't use an int as variable because it must be final to be used in a stream.
But You can create a class wrapping the int.
Then declare the variable holding this class as final.
Changing the content of the inner int variable.
public void findMax(List<List<Route>> routeLists) {
final IntWrapper dWrapper = new IntWrapper();
routeLists.forEach(e-> {
e.forEach(ee -> {
dWrapper.value += ee.getDistance();
});
});
int d = dWrapper.value;
... doing some other operation with d
}
public class IntWrapper {
public int value;
}

Having side effects is discouraged (or even forbidden?) in the functions used in a stream.
A better way would be one of
routeLists.stream()
.flatMapToInt(innerList -> innerList.stream()
.mapToInt(Route::getDistance))
.sum()
or
routeLists.stream()
.mapToInt(innerList -> innerList.stream()
.mapToInt(Route::getDistance).sum())
.sum()
The first will, for each sublist, create a stream of distances. All these streams will become flattened and summed at once.
The second will create the sum of each sublist and then add all those sums together again.
They should be equivalent, but I am not sure if the one or other is better in terms of performance (i. e., if flattening the streams is more expensive than summing).
A third alternative of flattening the lists and then getting and summing the distances is covered by Andy Turner's answer.

Related

Using effectively final variable

Question related to frames of function and effective finality of variables.
int lenMin = list.get(0).length();
for (String s : list)
if (s.length() < lenMin)
lenMin = s.length();
list
.stream()
.filter(s -> lenMin == s.length())
.forEach(System.out::println);
st:1. here we create a variable.
st: 3-5 here we do something with it (change it).
st:9 the lenMin variable is underlined in red.
Effectivity finality we cannot change, but can we use it? I know that the lambda has a new frame, but if we do this:
int len = lenMin;
list
.stream()
.filter(s -> len == s.length())
.forEach(System.out::println);
then there will be no error.
Please explain why this is happening?
Functions that can close over variables need a way to capture those variables.
If a variable can't change, then you can easily capture variables by copying their values.
Java does exactly that. Java lambdas, and inner classes simply correspond to classes that have an extra field for each captured variable.
The JVM only understands flat classes; nested and inner classes are compiler fictions.
Runnable f() {
int answer = 42;
class C extends Runnable {
public void run() { System.out.println(answer); }
}
return new C();
}
compiles to something equivalent to
class C {
private int answer; // Capturing field
C(int answer) { this.answer = answer }
void run() { System.out.println(this.answer); }
}
Runnable f() {
int answer = 42;
return new C(answer);
}
This change is called closure conversion.
As long as answer is only assigned once, javac can do simple closure conversion: copying answer into any classes and lambdas that need it.
But simple copying doesn't work if a local variable might change after being captured.
int answer = 42;
Runnable c = new C();
answer += 1;
c(); // Should this print 42 or 43?
Programmers familiar with languages that allow for reassignment of closed-over variables would get confused if the above didn't behave like the JavaScript below.
let answer = 42;
let c = () => console.log(answer);
answer += 1;
c(); // Logs 43
Java could allow for mutable closed-over variables by doing more complicated closure conversion. For example, instead of copying answer, storing answer in a shared object and rewriting reads&writes to be reads/writes of a property or element of that shared object.
For example,
int[] answerBox = new int[1];
answerBox[0] = 42; // assignment
...
answerBox[0] = 43; // re-assignment
...
System.out.println(answerBox[0]);
...
Java's designers decided not to do that though; capturing by-reference the way JavaScript does would introduce a host of subtle complications. JavaScript is single threaded, but the JVM is not, so imagine when a closed over long variable is suddenly assigned in more than one thread.
This is not hard to work around though as long as you don't need to mutate captured state after creating the capturing value.
Runnable f() {
int x = 1;
x += 1;
return () -> System.out.println(x); // ERROR
}
The above fails, but the below works; we simply store the state of the non-effectively-final x in an effectively final finalX that the lambda can capture.
Runnable f() {
int x = 1;
x += 1;
int finalX = x;
return () -> System.out.println(finalX); // OK
}
So the question is: why one has to introduce a new copy, to have a variable, that is effectively final (= could be made final). Here len.
int len = lenMin;
list
.stream()
.filter(s -> len == s.length())
.forEach(System.out::println);
The reason that the lambda (inside filter) is an anonymous implemented interface instance, that uses len as follows: as it is a local variable, it copies it into a local interface variable with the same name len.
But now one has two variables (though same names). As the lambda theoretically could run in another thread, one has two threads that can change same named variables differently. The language designers did not want to allow two lens with different values, and simply required that the variable is not changed, effectively final.
Here it would not be dangerously misleading, but assume you later assign to len at the end or inside a lambda, and perhaps use .parallelStream(). Then suddenly a compile error must be given at an unchanged piece of code.
That is an additionally sufficient reason to keep the rule simple: a local variable used inside a lambda must be effectively final.

Lambda expression return type in Java [duplicate]

This question already has answers here:
What is the breakdown for Java's lambda syntax?
(4 answers)
Closed 4 years ago.
I'm learning about Lambda in Java and I try to understand it. For example I have this following code:
#FunctionalInterface
interface Square
{
int calculate(int x);
}
class Test
{
public static void main(String args[])
{
int a = 5;
Square s = (int x) -> x*x;
int ans = s.calculate(a);
System.out.println(ans);
}
}
I do not understand this statement Square s = (int x) -> x*x; I see that s is a reference variable of type Square. But I don't understand what exactly is this (int x) -> x*x. Is this a method definition? What is the return type of this method? I think it should be int because the return type of calculate method is int. Any feedback will be appreciated.
Your lambda expression can be replaced by anonymous class :
Square s = new Square() {
#Override
public int calculate(int x) {
return x * x;
}
};
So (int x) -> x*x is just implementation of calculate method that takes int argument and return int value. By the way it is not necessary to specify parameter type. You can do like :
Square s = x -> x*x;
Now you have object of type Square and you can call the calculate method that was defined before in lambda expression:
int squared = s.calculate(5);
A lambda can also be thought of as a quick way to define (or redefine) an abstract function. (They call it syntactic sugar.) So you could write it like this, also:
Square s;
s = x -> x*x;
System.out.println (s.calculate(5)); // 25
What's happening there is you're filling in the blanks of the function declaration. The argument is 'x' and the body of the function (aka method in Java) is 'return x*x'.
Consider that you could do this next, also: (Note addition of curly braces to support a multi-line block. The return is explicitly declared, then. Also, the input type can be explicitly declared, too -- visual indicator to reference overloading.)
s = (int x) -> { return x*x*x ; } ; // brackets allow multi-line operations
System.out.println (s.calculate(2)); // 8
So, there is the capacity to dynamically reassign new operations to an abstract method in a very shorthand mechanism.
Consider that the interface could also define something like this:
int calculate(String x); // note change in argument type -- overloading
At that point you could do something like this: (Type of s is a String.)
s = s -> { return s.length()*2 ; } ;
System.out.println (s.calculate("It!")); // 6
Bottom line is that lambdas provide an incredibly flexible and shorthand method to define and redefine methods on the fly.
It's lambda syntax. It's syntactic sugar for ...
Square s = new Square ()
{
#Override
public int calculate (int x)
{
return x*x;
}
}
The calculate method in your Square interface accepts an int and returns an int, but there is no implementation of the logic how to calculate the return value as it has no method body { ....... }like other methods you may know.
So the snippet that you have doesn't point to an int but implements the logic ( how to calculate). It might be misleading with the name Square but following expressions are valid:
Square s = (int x) -> x*x; // your example
Square s1 = (int x) -> x*x*x; // takes an int x and returns the cube of x
Square s2 = (int x) -> x+42; // takes an int x and returns x+42
Square s3 = (int x) -> x%2; // takes an int and returns 0 if x is even 1 otherwise

How to define multiple variables in single statement

In Python, I can define two variables with an array in one line.
>>>[a,b] = [1,2]
>>>a
1
>>>b
2
How do I do the same thing in Java?
I have a couple of variables in class PCT which type is final. Is there a way to define them in one line in a Python like fashion? The following format clearly does not work in Java. I could define them separately, but it will call the parseFile method twice which I want to avoid.
public class PCT {
final int start;
final int stop;
public PCT (File file) {
//......
//......
// the following statement does not compile
[start, stop] = parseFile(file);
}
public int[] parseFile(File f) {
int[] aa = new int[2];
// ....
// ....
return aa;
}
}
You can define multiple variables like this :
double a,b,c;
Each variable in one line can also be assigned to specific value too:
double a=3, b=5.2, c=3.5/3.5;
One more aspect is, while you are preparing common type variable in same line then from right assigned variables you can assign variable on left, for instance :
int a = 4, b = a+1, c=b*b;
Noticed, you can also practice arithmetic operations on variable by remaining in the same line.
This is not possible, but you also don't need to call parseFile twice.
Write your code like this:
int [] temp = parseFile(file);
start = temp[0];
stop = temp[1];
Python (I believe) supports multiple return values. Java obeys C conventions, and so doesn't permit it. Since that isn't part of the language, the syntax for it isn't either, meaning slightly gross hacks like the temp array are needed if you're doing multiple returns.
When declaring several variables of the same type, you can do the following:
int a = 1, b = 2, c = 3; //etc.
If you literaly mean line; as long as you place a semicolon in between two statements, they are executed as if there is a new line in between so you can call:
a = 1; b = 2;
You can even compress an entire file into a oneliner, by removing comment (that scope to the end of the line). Spacing (space, tab, new line,...) is in general removed from the Java files (in memory) as first step in the Java compiler.
But you are probably more interested in a singe statement. Sytax like [start, stop] = parseFile(file); is not supported (at least not for now). You can make a onliner:
int[] data = parseFile(file); start = data[0]; stop = data[1];
Maybe this is what you're looking for:
int array[] = {1,2};
Java array assignment (multiple values)
If you're looking to explicitly assign to each element, I don't think you can do that within one assignment, as a similar concept with the 2-d example below. Which seems like what you want as Jeremy's answers specifies.
Explicitly assigning values to a 2D Array?
Maybe
public class PCT
{
final Point pos; // two ints!
public PCT (File file)
{
pos = parseFile(file);
}
public int[] parseFile(File f)
{
Point aa = new Point();
// ....
// ....
return aa;
}
}

Nested functions in Java

Are there any extensions for the Java programming language that make it possible to create nested functions?
There are many situations where I need to create methods that are only used once in the context of another method or for-loop. I've been unable to accomplish this in Java so far, even though it can be done easily in JavaScript.
For example, this can't be done in standard Java:
for(int i = 1; i < 100; i++){
times(2); // Multiply i by 2 and print i
times(i); // Square i and then print the result
public void times(int num){
i *= num;
System.out.println(i);
}
}
Java 8 introduces lambdas.
java.util.function.BiConsumer<Integer, Integer> times = (i, num) -> {
i *= num;
System.out.println(i);
};
for (int i = 1; i < 100; i++) {
times.accept(i, 2); //multiply i by 2 and print i
times.accept(i, i); //square i and then print the result
}
The () -> syntax works on any interface that defines exactly one method. So you can use it with Runnable but it doesn't work with List.
BiConsumer is one of many functional interfaces provided by java.util.function.
It's worth noting that under the hood, this defines an anonymous class and instantiates it. times is a reference to the instance.
The answer below is talking about the closest you can get to having nested functions in Java before Java 8. It's not necessarily the way I'd handle the same tasks which might be handled with nested functions in JavaScript. Often a private helper method will do just as well - possibly even a private helper type, which you create an instance of within the method, but which is available to all methods.
In Java 8 of course, there are lambda expressions which are a much simpler solution.
The closest you can easily come is with an anonymous inner class. That's as close as Java comes to closures at the moment, although hopefully there'll be more support in Java 8.
Anonymous inner classes have various limitations - they're obviously rather wordy compared with your JavaScript example (or anything using lambdas) and their access to the enclosing environment is limited to final variables.
So to (horribly) pervert your example:
interface Foo {
void bar(int x);
}
public class Test {
public static void main(String[] args) {
// Hack to give us a mutable variable we can
// change from the closure.
final int[] mutableWrapper = { 0 };
Foo times = new Foo() {
#Override public void bar(int num) {
mutableWrapper[0] *= num;
System.out.println(mutableWrapper[0]);
}
};
for (int i = 1; i < 100; i++) {
mutableWrapper[0] = i;
times.bar(2);
i = mutableWrapper[0];
times.bar(i);
i = mutableWrapper[0];
}
}
}
Output:
2
4
10
100
Is that the output you get from the JavaScript code?
I think that the closest you can get to having nested functions in Java 7 is not by using an anonymous inner class (Jon Skeet's answer), but by using the otherwise very rarely used local classes. This way, not even the interface of the nested class is visible outside its intended scope and it's a little less wordy too.
Jon Skeet's example implemented with a local class would look as follows:
public class Test {
public static void main(String[] args) {
// Hack to give us a mutable variable we can
// change from the closure.
final int[] mutableWrapper = { 0 };
class Foo {
public void bar(int num) {
mutableWrapper[0] *= num;
System.out.println(mutableWrapper[0]);
}
};
Foo times = new Foo();
for (int i = 1; i < 100; i++) {
mutableWrapper[0] = i;
times.bar(2);
i = mutableWrapper[0];
times.bar(i);
i = mutableWrapper[0];
}
}
}
Output:
2
4
10
100
Such methods are sometimes called closures. Have a look at Groovy – perhaps you will prefer it to Java. In Java 8 there will probably be closures as well (see JSR335 and deferred list).
For non-argument method you can create Runnable object
private static void methodInsideMethod(){
Runnable runnable = new Runnable(){
#Override
public void run(){
System.out.println("Execute something");
}
};
for(int i = 0; i < 10; i++){
runnable.run();
}
}
Consider making an anonymous local class and using its initializer block to do the work:
public class LocalFunctionExample {
public static void main(final String[] args) {
for (final int i[] = new int[] { 1 }; i[0] < 100; i[0]++) {
new Object() {
{
times(2); //multiply i by 2 and print i
times(i[0]); //square i and then print the result
}
public void times(final int num) {
i[0] *= num;
System.out.println(i[0]);
}
};
}
}
}
Output:
2
4
10
100
(The "final wrapper trick" is not automatically required with this technique, but was needed here to handle the mutation requirement.)
This works out to be almost as concise as the lambda version, but you get to use whatever method signatures you want, they get to have real parameter names, and the methods are called directly by their names - no need to .apply() or whatnot. (This kind of thing sometimes makes IDE tooling work a little better too.)
I don't know if anyone else has figured this out, but apparently you can do magic with the var keyword that comes with Java 10 and above. This saves you from having to declare an interface if you don't have one that will work for you.
public class MyClass {
public static void main(String args[]) {
var magic = new Object(){
public void magic(){
System.out.println("Hello World!");
}
};
magic.magic();
}
}
I have tested it and it works. I haven't found a Java compiler that lets you do a simple share yet.
I hate to use the forbidden word but you could use a goto statement to create an an effective subroutine inside the method. It is ugly and dangerous but much easier than what was shown in previous answers. Although the private method with a call inside of the first method is much better, and serves you needs just fine. I don't know why you would want to use a nested method for something as simple as this.

Is it possible to write swap method in Java? [duplicate]

This question already has answers here:
How to write a basic swap function in Java [duplicate]
(19 answers)
Java method to swap primitives
(8 answers)
Closed 6 years ago.
Here is the question: write a method that swaps two variables. These two variables should be primitives. It doesn't need to be generic e.g. two int variables. Is there a way?!
While it is not possible to write a function that simply swaps two variables, it is possible to write a helper function that allows you to:
Swap two variables using only one statement
Without temporary variables in the caller's code
Without 'boxing' primitives
With a few overloads (one of them using generics), it works for any type
That's how you could do it:
int returnFirst(int x, int y) {
return x;
}
<T> T returnFirst(T x, T y) {
return x;
}
// other overloads as needed
int a = 8, b = 3;
a = returnFirst(b, b = a); // try reading this as a = b; b = a;
System.out.println("a: " + a + ", b: " + b); // prints a: 3, b: 8
This works because the Java language guarantees (Java Language Specification, Java SE 7 Edition, section 15.12.4.2) that all arguments are evaluated from left to right (unlike some other languages, where the order of evaluation is undefined), so the execution order is:
The original value of b is evaluated in order to be passed as the first argument to the function
The expression b = a is evaluated, and the result (the new value of b) is passed as the second argument to the function
The function executes, returning the original value of b and ignoring its new value
You assign the result to a
If returnFirst is too long, you can choose a shorter name to make code more compact (e.g. a = sw(b, b = a)).
Suppose you need to swap many variables of different types one after the other. By using returnFirst there's no need for intAux, objAux, etc. There's less risk of mistakenly using the wrong variable somewhere, because there are no extra variables (in the caller, at least).
Without using an array or objects, no, it is not possible to do it within a method.
Check out this JavaWorld article that explains it in detail:
http://www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526-pass.html
A swap of two primitives will never work because primitives are passed by value in Java. You can't even write a method to swap two objects for that matter.
Like #Thomas said, the only thing you could do is have your primitives contained within other objects/arrays and modify those.
One-liner for any primitive numbers:
a += (b - (b = a));
You can make a generic version of #marcus's swap method that swaps any number of objects of the same type:
<T> T swap(T... args) { // usage: z = swap(a, a=b, b=c, ... y=z);
return args[0];
}
b = swap(a, a=b);
z = swap(x, x=y, y=z);
In java5, the closest I can think of, which may help you, is :
The AtomicInteger class (and others) have getAndSet() atomic methods ..
To write a swap method that swaps primitives you'd have to have the concept of "out" variables, i.e. variables whose values are passed up to the calling context. C# has those but you must still specify that they're out variables.
This function will swap two ints
Integer[] swap(int a, int b){
return new Integer[]{b,a};
}
Here's a method that swaps two primitive variables
private void swap(){
int a = 1;
int b = 2;
int temp = a;
a = b;
b = temp;
}
It might not be of much use though ;)
Ok seriously, it could be done if the variables are class level:
public class MyClass{
// excuse horrible coding practice of public mutable fields
public int a = 1;
public int b = 2;
public void swap(){
int temp = a;
a = b;
b = temp;
}
}
Again though, I fail to see what the use of this could be
I have read the above answers seeking an explanation as to why it is said that a swapping program cannot be written in java in the way it is written in c++.
I did the following way
program screenshot
As Thomas Owens said. You could probably do it in C by passing variables by &reference, but afaik not in Java without using objects.
Yes it is possible to swap two variable using a method.
But you should declare that method with empty parentheses and then call it by
reference(empty parentheses) .
Here is an example that illustrates swapping of two variable using a method.
public class Swapping
{
static String A="Apple";
static String B="Bat";
public static void swap()
{
String k;
k=A;
A=B;
B=k;
}
public static void main(String[] args)
{
System.out.println("Before swapping");
System.out.println("A= "+A);
System.out.println("B= "+B);
swap();
System.out.println("After swapping");
System.out.println("A= "+A);
System.out.println("B= "+B);
}
}
By compiling the above code the output comes as follows:
Before swapping
A= Apple
B= Bat
After swapping
A= Bat
B= Apple
//In case of call by reference original value is changed if we made changes in the called method
public class Swap
{
public static void main (String[]args)
{
int y = 5;
int x = 4;
int c;
System.out.println("y = "+y);
System.out.println("x = "+x);
c=x; //c = 4
x=y; //x = 5;
y=c;
System.out.println("\n");
System.out.println("y= "+y);
System.out.println("x= "+x);
}
}

Categories