TIL #7: Java Lambda Puzzler

Today, a colleague asked me how they can pass a java.util.Stream to a function that accept an java.lang.Iterable.

Let’s suppose we have a following function that accepts an Iterable.

public static void doSth(Iterable<String> iterable){
        iterable.forEach(System.out::println);
 }

The calling function has a Stream that it want to pass to the doSth function.

public static void main(String[] args) throws IOException {
        Stream<String> lines = Files.lines(Paths.get("src", "main", "resources", "names.txt"));
}

One way we could easily achieve this is by collecting the Stream into a Collection like List. As List is an Iterable so we can pass it. This is should below

Stream<String> lines = Files.lines(Paths.get("src", "main", "resources", "names.txt"));
doSth(lines.collect(Collectors.toList()));

This works but what if Stream is big and collecting into an in-memory data structure like List leads to java.lang.OutOfMemoryError: Java heap space.

I googled around and found a nice Lambda hack.

Stream<String> lines = Files.lines(Paths.get("src", "main", "resources", "names.txt"));
doSth(lines::iterator);

I have worked a lot on Java 8 but first time I looked at it I couldn’t figure out how it works. If you know Java 8, give it a shot.

The magic here is that Iterable interface has a single abstract method iterator.

public interface Iterable<T> {
    Iterator<T> iterator();
}

This means we can write it as following Lambda function.

Iterable<T> iterable = () -> iterator();

In our case, Stream has an iterator method. So, we can convert Stream to Iterable by defining a lambda function as shown below.

Stream<String> lines = Files.lines(Paths.get("src", "main", "resources", "names.txt"));
doSth(() -> lines.iterator());

You can refactor the Lambda to a method reference.

Stream<String> lines = Files.lines(Paths.get("src", "main", "resources", "names.txt"));
doSth(lines::iterator);

Can we use () -> iterator() in the for-each loop

I wondered if we can use the lambda expression in the for-each loop

for (String str : () -> lines.iterator()) {
    System.out.println(str);
}

This looks like a valid use case. As for-each loop works with types that implement Iterable interface. But, it turns out the code does not compile. It gives Lambda expression not implemented here error.

The answer for this is mentioned in the JSR335

Deciding what contexts are allowed to support poly expressions 
is driven in large part by the practical 
need for such features:

The expression in an enhanced for loop is not in a 
poly context because, as the construct is currently defined, 
it is as if the expression were a receiver: 
exp.iterator() (or, in the array case, exp[i]). 
It is plausible that an Iterator could be wrapped 
as an Iterable in a for loop via a 
lambda expression (for (String s : () -> stringIterator)), 
but this doesn't mesh very well with the semantics of Iterable.

Another Interesting thing to note is that Iterable is not marked as @FunctionalInterface. I don’t know the exact reason why Iterable is not marked as @FunctionalInterface. My guess is that because Iterable has special semantics in Java so they didn’t explicitly marked it @FunctionalInterface.

Advertisements

IBM DeveloperWorks Introducing Spring Roo, Part 4: Rapid application development in cloud with Spring Roo and Cloud Foundry

Take the rapid development of Roo a step further by creating applications to work in the cloud with Cloud Foundry, the first open platform as a service project created by VMWare. Learn more about the environment and then deploy an application into Cloud Foundry using the Roo shell. Read about it here http://www.ibm.com/developerworks/opensource/library/os-springroo4/index.html

Java Puzzler : They just find me !!

Couple of days back I wrote a piece of code which was behaving in an unexpected manner. I was confused what was happening. Take a look at the sample code below and predict its behavior

package com.shekhar;

public class JavaPuzzler {

	public static void main(String[] args) {
		JavaPuzzler javaPuzzler = new JavaPuzzler();
		javaPuzzler.doSth();
	}

	public void doSth() {
		float f = 1.2f;
		if (f >= 1.0) {
			f = 0.9999999999999f;
		}
		InnerClass innerClass = new InnerClass(f);
		System.out.println(innerClass.getValue());
	}

	private class InnerClass {

		private float value;

		public InnerClass(float value) {
			if (value >= 1.0f) {
				throw new IllegalArgumentException(
						"Value can't be greater than 1.0f");
			}

			this.value = value;
		}

		public float getValue() {
			return value;
		}
	}
}

My initial expectation was that I would get value 0.9999999999999f as answer.Try it and find the answer. Share your answer and reasoning in comments.

Top 10 New Features in Maven 3

Maven 3.0 was just released and the Java build tool has come a long way since version 2 was released almost six years back. Maven 2 had reached a stage where it was difficult to extend and its code was difficult to understand. In version 3.0 many of the Maven internals have been revamped to overcome all the issues associated with Maven 2. In this article, I run down the top 10 features in Maven 3.

Read More

New Java Puzzler Found while reading Java Puzzler book

Today, while solving puzzles from Java Puzzler book I myself created a new Java Puzzle. So, in this blog I am writing about that puzzle.

Puzzle

Will the code given below results in an infinite loop.


public class MyJavaPuzzle {

 public static void main(String[] args) {
 Double i = Double.NaN;
 while(i != i){
 System.out.println("Infinite Loop");
 }
 }
}

Solve this puzzle and have fun. Happy Puzzling!!!

Post your answer and explanation in comments.

Java Puzzlers on local variable initialization

Intent of my blog

Some time back, i posted a blog on common interview questions on overriding.The blog was very popular on dzone so i decided to write some of the java puzzlers on local variable initialization.One thing which should be kept in mind is that Local variables should be initalized before they are used.Knowing this fact try to answer these questions.

Local Variable Initialization Puzzlers

Question1


public class Question1{
 public static void main(String[] args) {
 int x;
 int y = 10;
 if (y == 10) {
 x = y;
 }
 System.out.println("x is " + x);
 }
}

Question 2


class Question2{
 public static void main(String[] args) {
 int x;
 if(true){
 x = 10;
 }
 System.out.println("x is " + x);
 }
}

Question 3


class Question3{
 public static void main(String[] args) {
 int x;
 final int y = 10;
 if(y == 10){
 x = 10;
 }
 System.out.println("x is " + x);

 }
}

Question 4


class Question4{
 static int y = 10;

 public static void main(String[] args) {
 int x ;
 if(y == 10){
 x = 10;
 }
 System.out.println("x is " + x);
 }
}

Question 5


class Question5{
 static final int y = 10;

 public static void main(String[] args) {
 int x ;
 if(y == 10){
 x = 10;
 }
 System.out.println("x is " + x);
 }
}

Again, like the previous post, i am not posting the solutions because i dont want to take away the fun. So, play with these and have fun.

Again fallen into java puzzler trap– Another Java Puzzler

Intent of My Blog
Today, while writing a piece of code, i found that i have again fallen into a java trap.This is a java puzzler that i read in java puzzler book.

What is the output of this java puzzler?

public class JavaPuzzler {

public static void main(String[] args) {
JavaPuzzler javaPuzzler = null;
System.out.println(javaPuzzler.get());
}

private static String get(){
return "i am a java puzzler";
}

}

Before reading the answer ,please try running this in eclipse and see whether you got it correct.

Solution

You might think that it should throw NullPointerException because the main method invokes get() method  on local variable which is initialized to null, and you can’t invoke a method on null.

But if you run this program, you will see that it prints “i am a java puzzler” . The reason  is that get() is a static method.