Search code examples
performancejava-8functional-interface

When to use functional interface? (Java 8)


I recently switched over to developing my software for Java 8, and I've been slowly improving my use of Java 8 and becoming comfortable with Java 8, and in doing so I've started implementing more and more functional interfaces, and recently NetBeans has started to suggest that I swap some of my for loops over to functional interfaces, but from the way the program is running it seems much slower than simply using a for loop (1.9 sec runtime vs. .9 sec respectively). So my question is-- is it worth using functional interfaces in the place of for loops? When in general should one use functional interfaces? Are functional interfaces more efficient in some other ways? Thanks in advance.


Solution

  • if your lambdas do not use many capturing variables, then i believe that the performance will be more comparable to a standard for loop. the the advantages of using lambdas are easier parallelization (although for ordered streams this could potentially result in slower performance), and an easier to read syntax. also be aware that the hotspot compiler will change the results over time (your first loop execution will most likely be slower than your last).

    i do not know the specifics, but in the worst case situation, you lambda may be implemented as an anonymous class. in the best case, it will just be a MethodHandle.

    a quick test:

    public class Test {
    
        public static void main(String... args) {
            Random r = new Random(42);
            for(int i = 0; i < 10; i++) {
                testFor();
                testLambda();
            }
        }
    
        protected static final int TestLength = 1024 * 1024 * 16;
    
        protected static int result;
    
        protected static void testFor() {
            Random r = new Random(42);
            long start = System.currentTimeMillis();
            for(int i = 0; i < TestLength; i++) {
                result = r.nextInt(TestLength);
            }
            long end = System.currentTimeMillis();
            System.out.printf("testFor = %dms%n", end - start);
        }
    
        protected static void testLambda() {
            Random r = new Random(42);
            IntStream stream = IntStream.iterate(0, i -> r.nextInt(1024 * 1024));
            long start = System.currentTimeMillis();
            stream.limit(TestLength).forEach(i -> {result = i;});
            long end = System.currentTimeMillis();
            System.out.printf("testLambda = %dms%n", end - start);
        }
    
    }
    

    the results:

    testFor = 209ms
    testLambda = 207ms
    testFor = 210ms
    testLambda = 206ms
    

    for a parallel stream the results where actually slower (around 2x on my machine) because the stream was ordered and each thread has a lot of synchronization overhead, compared to the work being done (just result = i)