Функция Java 8 Lambda, которая генерирует исключение?

Я знаю, как создать ссылку на метод с параметром String и возвращает int, это:

Function<String, Integer>

Однако это не работает, если функция генерирует исключение, например, оно определяется как:

Integer myMethod(String s) throws IOException

Как я могу определить эту ссылку?

Ответы

Ответ 1

Вам нужно будет выполнить одно из следующих действий.

  • Если это ваш код, тогда определите свой собственный функциональный интерфейс, который объявит исключенное исключение

    @FunctionalInterface
    public interface CheckedFunction<T, R> {
       R apply(T t) throws IOException;
    }
    

    и используйте его

    void foo (CheckedFunction f) { ... }
    
  • В противном случае wrap Integer myMethod(String s) в методе, который не объявляет проверенное исключение:

    public Integer myWrappedMethod(String s) {
        try {
            return myMethod(s);
        }
        catch(IOException e) {
            throw new UncheckedIOException(e);
        }
    }
    

    а затем

    Function<String, Integer> f = (String t) -> myWrappedMethod(t);
    

    или

    Function<String, Integer> f =
        (String t) -> {
            try {
               return myMethod(t);
            }
            catch(IOException e) {
                throw new UncheckedIOException(e);
            }
        };
    

Ответ 2

Фактически вы можете расширить ConsumerFunction и т.д.) с помощью нового интерфейса, который обрабатывает исключения - с использованием методов Java 8 по умолчанию!

Рассмотрим этот интерфейс (extends Consumer):

@FunctionalInterface
public interface ThrowingConsumer<T> extends Consumer<T> {

    @Override
    default void accept(final T elem) {
        try {
            acceptThrows(elem);
        } catch (final Exception e) {
            // Implement your own exception handling logic here..
            // For example:
            System.out.println("handling an exception...");
            // Or ...
            throw new RuntimeException(e);
        }
    }

    void acceptThrows(T elem) throws Exception;

}

Затем, например, если у вас есть список:

final List<String> list = Arrays.asList("A", "B", "C");

Если вы хотите его использовать (например, с помощью forEach) с помощью некоторого кода, который генерирует исключения, вы бы традиционно настроили блок try/catch:

final Consumer<String> consumer = aps -> {
    try {
        // maybe some other code here...
        throw new Exception("asdas");
    } catch (final Exception ex) {
        System.out.println("handling an exception...");
    }
};
list.forEach(consumer);

Но с помощью этого нового интерфейса вы можете создать экземпляр с помощью выражения лямбда и компилятор не будет жаловаться:

final ThrowingConsumer<String> throwingConsumer = aps -> {
    // maybe some other code here...
    throw new Exception("asdas");
};
list.forEach(throwingConsumer);

Или даже просто бросьте это, чтобы быть более кратким!:

list.forEach((ThrowingConsumer<String>) aps -> {
    // maybe some other code here...
    throw new Exception("asda");
});

Обновление. Похоже, есть очень приятная часть служебной библиотеки Durian под названием Errors, который может быть использован для решения этой проблемы с большей гибкостью. Например, в моей реализации выше я явно определил политику обработки ошибок (System.out... или throw RuntimeException), тогда как ошибки Durian позволяют применять политику "на лету" с помощью большого набора полезных методов. Спасибо за поделиться им, @NedTwigg!.

Использование образца:

list.forEach(Errors.rethrow().wrap(c -> somethingThatThrows(c)));

Ответ 3

Я думаю, класс Durian Errors объединяет многие плюсы различных предложенных выше предложений.

Чтобы включить Durian в свой проект, вы можете:

  • возьмите его из jcenter или maven central в com.diffplug.durian:durian:3.3.0
  • или просто скопируйте только два небольших класса в ваш код: Throwing.java и Errors.java

Ответ 4

Это не относится к Java 8. Вы пытаетесь скомпилировать что-то эквивалентное:

interface I {
    void m();
}
class C implements I {
    public void m() throws Exception {} //can't compile
}

Ответ 5

Отказ от ответственности: я еще не использовал Java 8, только читал об этом.

Function<String, Integer> не бросает IOException, поэтому вы не можете вставить в него код throws IOException. Если вы вызываете метод, ожидающий Function<String, Integer>, то лямбда, которую вы передаете этому методу, не может выбрасывать IOException, period. Вы можете либо написать лямбда, как это (я думаю, что это синтаксис лямбда, не уверен):

(String s) -> {
    try {
        return myMethod(s);
    } catch (IOException ex) {
        throw new RuntimeException(ex);
        // (Or do something else with it...)
    }
}

Или, если метод, по которому вы передаете лямбда, - это тот, который вы написали сами, вы можете определить новый функциональный интерфейс и использовать его как тип параметра вместо Function<String, Integer>:

public interface FunctionThatThrowsIOException<I, O> {
    O apply(I input) throws IOException;
}

Ответ 6

Если вы не против использовать стороннюю библиотеку (Vavr), вы можете написать

CheckedFunction1<String, Integer> f = this::myMethod;

Он также имеет так называемую Try monad, которая обрабатывает ошибки:

Try(() -> f.apply("test")) // results in a Success(Integer) or Failure(Throwable)
        .map(i -> ...) // only executed on Success
        ...

Пожалуйста, прочитайте больше здесь.

Отказ от ответственности: Я создатель Вавра.

Ответ 7

Вы можете использовать обходную упаковку

Function<String, Integer> func1 = s -> Unthrow.wrap(() -> myMethod(s));

или

Function<String, Integer> func2 = s1 -> Unthrow.wrap((s2) -> myMethod(s2), s1);

Ответ 8

Вы можете.

Расширение @marcg UtilException и добавление общего <E extends Exception> при необходимости: таким образом, компилятор заставит вас снова добавить предложения throw и все так же, как если бы вы могли исключить проверенные исключения изначально на java 8 потоках.

public final class LambdaExceptionUtil {

    @FunctionalInterface
    public interface Function_WithExceptions<T, R, E extends Exception> {
        R apply(T t) throws E;
    }

    /**
     * .map(rethrowFunction(name -> Class.forName(name))) or .map(rethrowFunction(Class::forName))
     */
    public static <T, R, E extends Exception> Function<T, R> rethrowFunction(Function_WithExceptions<T, R, E> function) throws E  {
        return t -> {
            try {
                return function.apply(t);
            } catch (Exception exception) {
                throwActualException(exception);
                return null;
            }
        };
    }

    @SuppressWarnings("unchecked")
    private static <E extends Exception> void throwActualException(Exception exception) throws E {
        throw (E) exception;
    }

}

public class LambdaExceptionUtilTest {

    @Test
    public void testFunction() throws MyTestException {
        List<Integer> sizes = Stream.of("ciao", "hello").<Integer>map(rethrowFunction(s -> transform(s))).collect(toList());
        assertEquals(2, sizes.size());
        assertEquals(4, sizes.get(0).intValue());
        assertEquals(5, sizes.get(1).intValue());
    }

    private Integer transform(String value) throws MyTestException {
        if(value==null) {
            throw new MyTestException();
        }
        return value.length();
    }

    private static class MyTestException extends Exception { }
}

Ответ 9

Другим решением, использующим оболочку Function, было бы вернуть либо экземпляр оболочки вашего результата, скажем, успех, если все прошло хорошо, либо экземпляр, скажем, Failure.

Некоторый код для уточнения вещей:

public interface ThrowableFunction<A, B> {
    B apply(A a) throws Exception;
}

public abstract class Try<A> {

    public static boolean isSuccess(Try tryy) {
        return tryy instanceof Success;
    }

    public static <A, B> Function<A, Try<B>> tryOf(ThrowableFunction<A, B> function) {
        return a -> {
            try {
                B result = function.apply(a);
                return new Success<B>(result);
            } catch (Exception e) {
                return new Failure<>(e);
            }
        };
    }

    public abstract boolean isSuccess();

    public boolean isError() {
        return !isSuccess();
    }

    public abstract A getResult();

    public abstract Exception getError();
}

public class Success<A> extends Try<A> {

    private final A result;

    public Success(A result) {
        this.result = result;
    }

    @Override
    public boolean isSuccess() {
        return true;
    }

    @Override
    public A getResult() {
        return result;
    }

    @Override
    public Exception getError() {
        return new UnsupportedOperationException();
    }

    @Override
    public boolean equals(Object that) {
        if(!(that instanceof Success)) {
            return false;
        }
        return Objects.equal(result, ((Success) that).getResult());
    }
}

public class Failure<A> extends Try<A> {

    private final Exception exception;

    public Failure(Exception exception) {
        this.exception = exception;
    }

    @Override
    public boolean isSuccess() {
        return false;
    }

    @Override
    public A getResult() {
        throw new UnsupportedOperationException();
    }

    @Override
    public Exception getError() {
        return exception;
    }
}

Простой вариант:

List<Try<Integer>> result = Lists.newArrayList(1, 2, 3).stream().
    map(Try.<Integer, Integer>tryOf(i -> someMethodThrowingAnException(i))).
    collect(Collectors.toList());

Ответ 10

Эта проблема тоже беспокоила меня; поэтому я создал этот проект.

С его помощью вы можете:

final ThrowingFunction<String, Integer> f = yourMethodReferenceHere;

Существует тотала 39 интерфейсов, определенных JDK, которые имеют такой эквивалент Throwing; все они @FunctionalInterface используются в потоках (база Stream, но также IntStream, LongStream и DoubleStream).

И так как каждый из них расширяет свою несовместимую копию, вы можете напрямую использовать их в lambdas:

myStringStream.map(f) // <-- works

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

Другие функции также доступны.

Ответ 11

У меня была эта проблема с Class.forName и Class.newInstance внутри лямбда, поэтому я просто сделал:

public Object uncheckedNewInstanceForName (String name) {

    try {
        return Class.forName(name).newInstance();
    }
    catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
        throw new RuntimeException(e);
    }
}

Внутри лямбда вместо вызова Class.forName( "myClass" ). newInstance() Я просто вызвал uncheckedNewInstanceForName ( "myClass" )

Ответ 12

Однако вы могли бы создать свой собственный функциональный интерфейс, который будет выглядеть следующим образом.

@FunctionalInterface
public interface UseInstance<T, X extends Throwable> {
  void accept(T instance) throws X;
}

затем реализуйте его с помощью Lambdas или ссылок, как показано ниже.

import java.io.FileWriter;
import java.io.IOException;

//lambda expressions and the execute around method (EAM) pattern to
//manage resources

public class FileWriterEAM  {
  private final FileWriter writer;

  private FileWriterEAM(final String fileName) throws IOException {
    writer = new FileWriter(fileName);
  }
  private void close() throws IOException {
    System.out.println("close called automatically...");
    writer.close();
  }
  public void writeStuff(final String message) throws IOException {
    writer.write(message);
  }
  //...

  public static void use(final String fileName, final UseInstance<FileWriterEAM, IOException> block) throws IOException {

    final FileWriterEAM writerEAM = new FileWriterEAM(fileName);    
    try {
      block.accept(writerEAM);
    } finally {
      writerEAM.close();
    }
  }

  public static void main(final String[] args) throws IOException {

    FileWriterEAM.use("eam.txt", writerEAM -> writerEAM.writeStuff("sweet"));

    FileWriterEAM.use("eam2.txt", writerEAM -> {
        writerEAM.writeStuff("how");
        writerEAM.writeStuff("sweet");      
      });

    FileWriterEAM.use("eam3.txt", FileWriterEAM::writeIt);     

  }


 void writeIt() throws IOException{
     this.writeStuff("How ");
     this.writeStuff("sweet ");
     this.writeStuff("it is");

 }

}

Ответ 13

Вы можете использовать ET для этого. ET - небольшая библиотека Java 8 для преобразования/перевода исключений.

С ET это выглядит так:

// Do this once
ExceptionTranslator et = ET.newConfiguration().done();

...

// if your method returns something
Function<String, Integer> f = (t) -> et.withReturningTranslation(() -> myMethod(t));

// if your method returns nothing
Consumer<String> c = (t) -> et.withTranslation(() -> myMethod(t));

ExceptionTranslator экземпляры являются потокобезопасными и могут совместно использоваться несколькими компонентами. Вы можете настроить более конкретные правила преобразования исключений (например, FooCheckedException -> BarRuntimeException), если хотите. Если других правил нет, проверенные исключения автоматически преобразуются в RuntimeException.

(Отказ от ответственности: я являюсь автором ET)

Ответ 14

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

Предложение Throws в FunctionalInterface не является хорошей идеей

Я думаю, что это, вероятно, не очень хорошая идея для принудительного ввода исключений IOException из-за следующих причин.

  • Это выглядит как анти-шаблон для Stream/Lambda. Вся идея заключается в том, что вызывающий абонент решит, какой код предоставить и как обрабатывать исключение. Во многих сценариях исключение IOException может не применяться для клиента. Например, если клиент получает значение из кеша/памяти вместо фактического ввода-вывода.

  • Кроме того, обработка исключений в потоках становится действительно отвратительной. Например, вот мой код будет выглядеть, если я использую ваш API

               acceptMyMethod(s -> {
                    try {
                        Integer i = doSomeOperation(s);
                        return i;
                    } catch (IOException e) {
                        // try catch block because of throws clause
                        // in functional method, even though doSomeOperation
                        // might not be throwing any exception at all.
                        e.printStackTrace();
                    }
                    return null;
                });
    

    Уродливый, не так ли? Более того, как я уже упоминал в своем первом пункте, метод doSomeOperation может или не может бросать IOException (в зависимости от реализации клиента/вызывающего), но из-за предложения throws в вашем методе FunctionalInterface мне всегда приходится писать попробуй поймать.

Что делать, если я действительно знаю, что этот API вызывает IOException

  • Тогда, вероятно, мы путаем FunctionalInterface с типичными интерфейсами. Если вы знаете, что этот API будет вызывать IOException, то, скорее всего, вы также знаете некоторое поведение по умолчанию/абстрактное поведение. Я думаю, вы должны определить интерфейс и развернуть свою библиотеку (с реализацией по умолчанию/абстрактной) следующим образом

    public interface MyAmazingAPI {
        Integer myMethod(String s) throws IOException;
    }
    

    Но проблема с try-catch все еще существует для клиента. Если я использую ваш API в потоке, мне все равно нужно обрабатывать IOException в отвратительном блоке try-catch.

  • Предоставьте по умолчанию удобный для потока API

    public interface MyAmazingAPI {
        Integer myMethod(String s) throws IOException;
    
        default Optional<Integer> myMethod(String s, Consumer<? super Exception> exceptionConsumer) {
            try {
                return Optional.ofNullable(this.myMethod(s));
            } catch (Exception e) {
                if (exceptionConsumer != null) {
                    exceptionConsumer.accept(e);
                } else {
                    e.printStackTrace();
                }
            }
    
            return Optional.empty();
        }
    }
    

    Метод по умолчанию принимает объект-потребитель как аргумент, который будет отвечать за обработку исключения. Теперь, с точки зрения клиента, код будет выглядеть следующим образом:

    strStream.map(str -> amazingAPIs.myMethod(str, Exception::printStackTrace))
                    .filter(Optional::isPresent)
                    .map(Optional::get).collect(toList());
    

    Ничего хорошего? Конечно, вместо Exception:: printStackTrace можно использовать логику или другую логику обработки.

  • Вы также можете выставить метод, похожий на https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html#exceptionally-java.util.function.Function-. Это означает, что вы можете открыть другой метод, который будет содержать исключение из предыдущего вызова метода. Недостаток заключается в том, что вы теперь делаете свои API полностью, что означает, что вам необходимо справиться с безопасностью потоков, и в конечном итоге это станет хитом производительности. Только вариант рассмотреть.

Ответ 15

Создайте настраиваемый тип возвращаемого значения, который будет распространять проверенное исключение. Это альтернатива созданию нового интерфейса, который отражает существующий функциональный интерфейс с небольшой модификацией "исключения исключений" в методе функционального интерфейса.

Определение

CheckedValueSupplier

public static interface CheckedValueSupplier<V> {
    public V get () throws Exception;
}

CheckedValue

public class CheckedValue<V> {
    private final V v;
    private final Optional<Exception> opt;

    public Value (V v) {
        this.v = v;
    }

    public Value (Exception e) {
        this.opt = Optional.of(e);
    }

    public V get () throws Exception {
        if (opt.isPresent()) {
            throw opt.get();
        }
        return v;
    }

    public Optional<Exception> getException () {
        return opt;
    }

    public static <T> CheckedValue<T> returns (T t) {
        return new CheckedValue<T>(t);
    }

    public static <T> CheckedValue<T> rethrows (Exception e) {
        return new CheckedValue<T>(e);
    }

    public static <V> CheckedValue<V> from (CheckedValueSupplier<V> sup) {
        try {
            return CheckedValue.returns(sup.get());
        } catch (Exception e) {
            return Result.rethrows(e);
        }
    }

    public static <V> CheckedValue<V> escalates (CheckedValueSupplier<V> sup) {
        try {
            return CheckedValue.returns(sup.get());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}

Использование

//  Don't use this pattern with FileReader, it meant to be an
//  example.  FileReader is a Closeable resource and as such should
//  be managed in a try-with-resources block or in another safe
//  manner that will make sure it is closed properly.

//  This will not compile as the FileReader constructor throws
//  an IOException.
    Function<String, FileReader> sToFr =
        (fn) -> new FileReader(Paths.get(fn).toFile());

// Alternative, this will compile.
    Function<String, CheckedValue<FileReader>> sToFr = (fn) -> {
        return CheckedValue.from (
            () -> new FileReader(Paths.get("/home/" + f).toFile()));
    };

// Single record usage
    // The call to get() will propagate the checked exception if it exists.
    FileReader readMe = pToFr.apply("/home/README").get();


// List of records usage
    List<String> paths = ...; //a list of paths to files
    Collection<CheckedValue<FileReader>> frs =
        paths.stream().map(pToFr).collect(Collectors.toList());

// Find out if creation of a file reader failed.
    boolean anyErrors = frs.stream()
        .filter(f -> f.getException().isPresent())
        .findAny().isPresent();

Что происходит?

Добавление "исключения исключений" к каждому функциональному интерфейсу в JDK будет самым грубым нарушением принципа DRY. Чтобы этого избежать, создается один функциональный интерфейс, который генерирует проверенное исключение (CheckedValueSupplier). Это будет единственный функциональный интерфейс, который позволяет проверять исключения. Все другие функциональные интерфейсы будут использовать CheckedValueSupplier для переноса любого кода, который выдает проверенное исключение.

Класс CheckedValue будет содержать результат выполнения любой логики, которая выдает проверенное исключение. Это предотвращает распространение проверенного исключения до момента, когда код пытается получить доступ к значению, которое содержит экземпляр CheckedValue.

Проблемы с этим подходом.

  • Мы сейчас бросаем "Исключение", эффективно скрывая определенный тип, который был изначально брошен.
  • Мы не знаем, что возникло исключение, пока не будет вызван CheckedValue#get().

Потребитель и др.

Некоторые функциональные интерфейсы (например, Consumer) должны обрабатываться по-другому, поскольку они не предоставляют возвращаемого значения.

Функция вместо потребителя

Один подход заключается в использовании функции вместо потребителя, которая применяется при обработке потоков.

    List<String> lst = Lists.newArrayList();
// won't compile
lst.stream().forEach(e -> throwyMethod(e));
// compiles
lst.stream()
    .map(e -> CheckedValueSupplier.from(
        () -> {throwyMethod(e); return e;}))
    .filter(v -> v.getException().isPresent()); //this example may not actually run due to lazy stream behavior

нагнетать

В качестве альтернативы вы всегда можете перейти на RuntimeException. Существуют и другие ответы, которые охватывают эскалацию проверенного исключения из Consumer.

Не потреблять.

Просто избегайте функциональных интерфейсов вместе и используйте цикл с хорошим ole-fashioned.

Ответ 16

Идиома CheckedException throw позволяет обходить CheckedException выражения Lambda. Обтекание CheckedException в RuntimeException не подходит для строгой обработки ошибок.

Он может использоваться как функция " Consumer используемая в коллекции Java.

Вот простая и улучшенная версия ответа на jib.

import static Throwing.rethrow;

@Test
public void testRethrow() {
    thrown.expect(IOException.class);
    thrown.expectMessage("i=3");

    Arrays.asList(1, 2, 3).forEach(rethrow(e -> {
        int i = e.intValue();
        if (i == 3) {
            throw new IOException("i=" + i);
        }
    }));
}

Это просто обертывает лямбду в ретроне. Это делает CheckedException отмененным любым Exception которое было выброшено в вашу лямбду.

public final class Throwing {
    private Throwing() {}

    @Nonnull
    public static <T> Consumer<T> rethrow(@Nonnull final ThrowingConsumer<T> consumer) {
        return consumer;
    }

    /**
     * The compiler sees the signature with the throws T inferred to a RuntimeException type, so it
     * allows the unchecked exception to propagate.
     * 
     * http://www.baeldung.com/java-sneaky-throws
     */
    @SuppressWarnings("unchecked")
    @Nonnull
    public static <E extends Throwable> void sneakyThrow(@Nonnull Throwable ex) throws E {
        throw (E) ex;
    }

}

Найдите полный код и модульные тесты здесь.

Ответ 17

Если вы не возражаете против использования сторонней библиотеки, cyclops-react, в которую я вношу вклад, вы можете использовать FluentFunctions API для записи

 Function<String, Integer> standardFn = FluentFunctions.ofChecked(this::myMethod);

ofChecked принимает jOOλ CheckedFunction и возвращает ссылку, смягченную обратно, на стандартную (непроверенную) JDK java.util.function.Function.

В качестве альтернативы вы можете продолжать работать с захваченной функцией с помощью FluentFunctions api!

Например, чтобы выполнить свой метод, повторите его до 5 раз и зарегистрировав его статус, вы можете написать

  FluentFunctions.ofChecked(this::myMethod)
                 .log(s->log.debug(s),e->log.error(e,e.getMessage())
                 .try(5,1000)
                 .apply("my param");

Ответ 18

По умолчанию Java 8 Function не позволяет бросать исключение и, как предлагается в нескольких ответах, есть много способов его достижения, один из способов:

@FunctionalInterface
public interface FunctionWithException<T, R, E extends Exception> {
    R apply(T t) throws E;
}

Определить как:

private FunctionWithException<String, Integer, IOException> myMethod = (str) -> {
    if ("abc".equals(str)) {
        throw new IOException();
    }
  return 1;
};

И добавьте throws или try/catch одно и то же исключение в метод вызова.

Ответ 19

Что я делаю, так это позволить пользователю дать значение, которое он действительно хочет в случае исключения. Итак, у меня что-то похожее на это

public static <T, R> Function<? super T, ? extends R> defaultIfThrows(FunctionThatThrows<? super T, ? extends R> delegate, R defaultValue) {
    return x -> {
        try {
            return delegate.apply(x);
        } catch (Throwable throwable) {
            return defaultValue;
        }
    };
}

@FunctionalInterface
public interface FunctionThatThrows<T, R> {
    R apply(T t) throws Throwable;
}

И это можно вызвать следующим образом:

defaultIfThrows(child -> child.getID(), null)

Ответ 20

В нескольких предложенных решениях используется общий аргумент E для передачи типа генерируемого исключения.

Сделайте еще один шаг и вместо того, чтобы передавать тип исключения, перейдите в Потребителя типа исключения, как в...

Consumer<E extends Exception>

Вы можете создать несколько повторно используемых вариантов Consumer<Exception>, которые будут охватывать общие потребности обработки исключений вашего приложения.

Ответ 21

Я сделаю нечто общее:

public interface Lambda {

    @FunctionalInterface
    public interface CheckedFunction<T> {

        T get() throws Exception;
    }

    public static <T> T handle(CheckedFunction<T> supplier) {
        try {
            return supplier.get();
        } catch (Exception exception) {
            throw new RuntimeException(exception);

        }
    }
}

использование:

 Lambda.handle(() -> method());

Ответ 22

Используйте Jool Library или скажите jOOλ library из JOOQ. Он не только предоставляет неконтролируемые интерфейсы обработки исключений, но также предоставляет класс Seq множеством полезных методов.

Кроме того, он содержит функциональные интерфейсы с до 16 параметрами. Кроме того, он предоставляет класс Tuple, который используется в разных сценариях.

Jool Git Ссылка

В частности, поиск библиотеки для пакета org.jooq.lambda.fi.util.function. Он содержит все интерфейсы от Java-8 с проверенным заранее. См. Ниже для справки: -

введите описание изображения здесь

Ответ 23

public void frankTest() {
    int pageId= -1;

    List<Book> users= null;
    try {
        //Does Not Compile:  Object page=DatabaseConnection.getSpringConnection().queryForObject("SELECT * FROM bookmark_page", (rw, n) -> new Portal(rw.getInt("id"), "", users.parallelStream().filter(uu -> uu.getVbid() == rw.getString("user_id")).findFirst().get(), rw.getString("name")));

        //Compiles:
        Object page= DatabaseConnection.getSpringConnection().queryForObject("SELECT * FROM bookmark_page", (rw, n) -> { 
            try {
                final Book bk= users.stream().filter(bp -> { 
                    String name= null;
                    try {
                        name = rw.getString("name");
                    } catch (Exception e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    return bp.getTitle().equals(name); 
                }).limit(1).collect(Collectors.toList()).get(0);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return new Portal(rw.getInt("id"), "", users.get(0), rw.getString("name")); 
        } );
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}