Когда использовать функциональный интерфейс? (Java 8)

Недавно я перешел на разработку своего программного обеспечения для Java 8, и я постепенно улучшал свое использование Java 8 и становился все более комфортным с Java 8, и при этом я начал реализовывать все больше и больше функциональных интерфейсов, и в последнее время NetBeans Я начал предлагать заменить некоторые циклы for на функциональные интерфейсы, но из-за того, что программа работает, она выглядит намного медленнее, чем просто использование цикла for (1,9 с по сравнению с 0,9 с соответственно). Поэтому мой вопрос: стоит ли использовать функциональные интерфейсы вместо циклов for? Когда вообще следует использовать функциональные интерфейсы? Функциональные интерфейсы более эффективны в других отношениях? Заранее спасибо.

1 ответ

Решение

Если ваши лямбды не используют много переменных захвата, то я считаю, что производительность будет более сопоставима со стандартом для цикла. Преимущества использования лямбда-выражений заключаются в упрощении распараллеливания (хотя для упорядоченных потоков это может привести к снижению производительности) и упрощении синтаксиса для чтения. Также имейте в виду, что компилятор горячей точки со временем изменит результаты (ваше первое выполнение цикла, скорее всего, будет медленнее, чем последнее).

Я не знаю специфику, но в худшем случае, вы лямбда может быть реализован как анонимный класс. в лучшем случае это будет просто MethodHandle.

быстрый тест:

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);
    }

}

результаты, достижения:

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

для параллельного потока результаты на самом деле медленнее (примерно в 2 раза на моей машине), потому что поток был упорядочен, и каждый поток имеет много накладных расходов на синхронизацию по сравнению с выполняемой работой (просто result = i)

Другие вопросы по тегам