java - lambdas - lambda expressions
¿Función de Java 8 Lambda que lanza excepción? (23)
Cree un tipo de retorno personalizado que propagará la excepción comprobada. Esta es una alternativa a la creación de una nueva interfaz que refleje la interfaz funcional existente con la ligera modificación de una "excepción de lanzamientos" en el método de la interfaz funcional.
Definición
CheckedValueSupplier
public static interface CheckedValueSupplier<V> {
public V get () throws Exception;
}
Valor verificado
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);
}
}
}
Uso
// Don''t use this pattern with FileReader, it''s 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();
¿Que esta pasando?
Agregar "excepciones de lanzamientos" a cada interfaz funcional en el JDK violaría el principio DRY de la manera más atroz. Para evitar esto, se crea una única interfaz funcional que lanza una excepción marcada ( CheckedValueSupplier
). Esta será la única interfaz funcional que permite excepciones comprobadas. Todas las demás interfaces funcionales aprovecharán CheckedValueSupplier
para envolver cualquier código que arroje una excepción marcada.
La clase CheckedValue
mantendrá el resultado de ejecutar cualquier lógica que arroje una excepción marcada. Esto evita la propagación de una excepción comprobada hasta el punto en el que el código intenta acceder al valor que contiene una instancia de CheckedValue
.
Los problemas con este enfoque.
- Ahora estamos lanzando "Excepción" ocultando efectivamente el tipo específico lanzado originalmente.
- Desconocemos que ocurrió una excepción hasta que se
CheckedValue#get()
.
Consumer et al
Algunas interfaces funcionales ( Consumer
por ejemplo) deben manejarse de una manera diferente, ya que no proporcionan un valor de retorno.
Función en lugar de consumidor
Un enfoque es usar una función en lugar de un consumidor, que se aplica cuando se manejan flujos.
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
Escalar
Alternativamente, siempre puede escalar a una RuntimeException
. Hay otras respuestas que cubren la escalada de una excepción marcada desde un Consumer
.
No consumas.
Simplemente evite las interfaces funcionales todas juntas y use un bucle de buena forma.
Sé cómo crear una referencia a un método que tiene un parámetro String
y devuelve un int
, es:
Function<String, Integer>
Sin embargo, esto no funciona si la función lanza una excepción, digamos que se define como:
Integer myMethod(String s) throws IOException
¿Cómo definiría esta referencia?
Creo que Errors combina muchas de las ventajas de las diversas sugerencias anteriores.
- Envuelva una función de lanzamiento en una interfaz funcional estándar de Java 8.
- Especifique fácilmente varias políticas para el manejo de errores
- Cuando se ajusta un método que devuelve un valor, hay una distinción importante entre especificar un valor predeterminado o volver a emitir una excepción RuntimeException.
- Lanzar versiones de las interfaces funcionales de Java 8.
- Similar a la respuesta de fge
- Interfaces estándar para lanzar excepciones específicas.
- Que aborda la preocupación de Zoltán.
Para incluir a Durian en su proyecto, puede:
- jcenter desde jcenter o maven central en
com.diffplug.durian:durian:3.3.0
- o simplemente copie y pegue solo dos clases pequeñas en su código:
Throwing.java
yErrors.java
De forma predeterminada, la Function Java 8 no permite lanzar excepciones y, como se sugiere en varias respuestas, hay muchas maneras de lograrlo, una forma es:
@FunctionalInterface
public interface FunctionWithException<T, R, E extends Exception> {
R apply(T t) throws E;
}
Definir como:
private FunctionWithException<String, Integer, IOException> myMethod = (str) -> {
if ("abc".equals(str)) {
throw new IOException();
}
return 1;
};
Y agregue throws
o try/catch
la misma excepción en el método del llamador.
En realidad, puede ampliar el Consumer
(y la Function
etc.) con una nueva interfaz que maneja las excepciones, ¡utilizando los métodos predeterminados de Java 8!
Considere esta interfaz (se extiende al 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;
}
Entonces, por ejemplo, si tienes una lista:
final List<String> list = Arrays.asList("A", "B", "C");
Si desea consumirlo (por ejemplo, con forEach
) con algún código que arroja excepciones, tradicionalmente habría configurado un bloque 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);
Pero con esta nueva interfaz, puede crear una instancia con una expresión lambda y el compilador no se quejará:
final ThrowingConsumer<String> throwingConsumer = aps -> {
// maybe some other code here...
throw new Exception("asdas");
};
list.forEach(throwingConsumer);
O incluso simplemente lanzarlo para ser más sucinto !:
list.forEach((ThrowingConsumer<String>) aps -> {
// maybe some other code here...
throw new Exception("asda");
});
Actualización : Parece que hay una muy buena parte de la biblioteca de utilidades de Durian llamada Errors que se puede usar para resolver este problema con mucha más flexibilidad. Por ejemplo, en mi implementación anterior, he definido explícitamente la política de manejo de errores ( System.out...
o throw RuntimeException
), mientras que los Errores de Durian le permiten aplicar una política sobre la marcha a través de una gran variedad de métodos de utilidad. Gracias por compartirlo , @NedTwigg !.
Uso de la muestra:
list.forEach(Errors.rethrow().wrap(c -> somethingThatThrows(c)));
Este problema me ha estado molestando también; Por eso he creado este proyecto .
Con ello podrás hacer:
final ThrowingFunction<String, Integer> f = yourMethodReferenceHere;
Hay una totla de 39 interfaces definidas por el JDK que tienen ese equivalente de Throwing
; Todos estos son @FunctionalInterface
s utilizados en secuencias (la Stream
base pero también IntStream
, LongStream
y DoubleStream
).
Y como cada uno de ellos extiende su contraparte de no lanzar, también puede usarlos directamente en las lambdas:
myStringStream.map(f) // <-- works
El comportamiento predeterminado es que cuando su lanzamiento lambda lanza una excepción marcada, se lanza una excepción ThrownByLambdaException
con la excepción marcada como la causa. Por lo tanto, puede capturar eso y obtener la causa.
Otras características están disponibles también.
Esto no es específico de Java 8. Está intentando compilar algo equivalente a:
interface I {
void m();
}
class C implements I {
public void m() throws Exception {} //can''t compile
}
Haré algo genérico:
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);
}
}
}
uso:
Lambda.handle(() -> method());
Hay muchas respuestas geniales ya publicadas aquí. Solo intento resolver el problema con una perspectiva diferente. Son solo mis 2 centavos, corrígeme si me equivoco en alguna parte.
La cláusula de lanzamiento en FunctionalInterface no es una buena idea
Creo que probablemente esta no sea una buena idea para imponer la excepción IOException debido a las siguientes razones
Esto me parece un anti-patrón para Stream / Lambda. La idea general es que la persona que llama decidirá qué código proporcionar y cómo manejar la excepción. En muchos casos, la excepción IOException podría no ser aplicable para el cliente. Por ejemplo, si el cliente obtiene valor de la memoria caché / memoria en lugar de realizar la E / S real.
Además, el manejo de excepciones en las secuencias se vuelve realmente horrible. Por ejemplo, aquí está mi código se verá como si utilizara su 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; });
Feo no es? Además, como mencioné en mi primer punto, el método doSomeOperation puede o no lanzar IOException (dependiendo de la implementación del cliente / llamante), pero debido a la cláusula throws en su método FunctionalInterface, siempre tengo que escribir el trata de atraparlo.
¿Qué hago si realmente sé que esta API produce IOException?
Entonces, probablemente estamos confundiendo FunctionalInterface con interfaces típicas. Si sabe que esta API lanzará IOException, entonces probablemente también conozca algún comportamiento predeterminado / abstracto. Creo que debería definir una interfaz e implementar su biblioteca (con implementación predeterminada / abstracta) de la siguiente manera
public interface MyAmazingAPI { Integer myMethod(String s) throws IOException; }
Pero, el problema try-catch todavía existe para el cliente. Si utilizo su API en secuencia, todavía necesito manejar la excepción IOException en el horrible bloque try-catch.
Proporcione una API por defecto para la transmisión de la siguiente manera
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(); } }
El método predeterminado toma el objeto consumidor como argumento, que será responsable de manejar la excepción. Ahora, desde el punto de vista del cliente, el código se verá así
strStream.map(str -> amazingAPIs.myMethod(str, Exception::printStackTrace)) .filter(Optional::isPresent) .map(Optional::get).collect(toList());
Bien cierto? Por supuesto, se podría usar el logger u otra lógica de manejo en lugar de Exception :: printStackTrace.
También puede exponer un método similar a https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html#exceptionally-java.util.function.Function- . Lo que significa que puede exponer otro método, que contendrá la excepción de la llamada al método anterior. La desventaja es que ahora está logrando que sus API sean con estado, lo que significa que necesita manejar la seguridad de subprocesos y que eventualmente se convertirá en un éxito de rendimiento. Sin embargo, sólo una opción a considerar.
Lo que estoy haciendo es permitir al usuario dar el valor que realmente desea en caso de excepción. Así que tengo algo parecido a esto
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;
}
Y esto puede ser llamado como:
defaultIfThrows(child -> child.getID(), null)
Otra solución que utilice un envoltorio de función sería devolver una instancia de un envoltorio de su resultado, digamos Éxito, si todo salió bien, o bien una instancia de, digamos Error.
Algún código para aclarar las cosas:
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;
}
}
Un caso de uso simple:
List<Try<Integer>> result = Lists.newArrayList(1, 2, 3).stream().
map(Try.<Integer, Integer>tryOf(i -> someMethodThrowingAnException(i))).
collect(Collectors.toList());
Puedes usar ET para esto. ET es una pequeña biblioteca de Java 8 para conversión / traducción de excepciones.
Con ET se ve así:
// 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
instancias de ExceptionTranslator
son seguras para subprocesos y pueden ser compartidas por varios componentes. Puede configurar reglas de conversión de excepciones más específicas (por ejemplo, FooCheckedException -> BarRuntimeException
) si lo desea. Si no hay otras reglas disponibles, las excepciones marcadas se convierten automáticamente a RuntimeException
.
(Descargo de responsabilidad: Soy el autor de ET)
Puedes usar la envoltura de unthrow
Function<String, Integer> func1 = s -> Unthrow.wrap(() -> myMethod(s));
o
Function<String, Integer> func2 = s1 -> Unthrow.wrap((s2) -> myMethod(s2), s1);
Si no le importa usar una biblioteca de terceros, con cyclops-react , una biblioteca a la que contribuyo, puede usar la API FluentFunctions para escribir
Function<String, Integer> standardFn = FluentFunctions.ofChecked(this::myMethod);
ofChecked toma un jOOλ CheckedFunction y devuelve la referencia suavizada a un JDK java.util.function.Function estándar (sin marcar).
Alternativamente, puedes seguir trabajando con la función capturada a través de la aplicación FluentFunctions.
Por ejemplo, para ejecutar su método, reinténtelo hasta 5 veces y registrando su estado puede escribir
FluentFunctions.ofChecked(this::myMethod)
.log(s->log.debug(s),e->log.error(e,e.getMessage())
.try(5,1000)
.apply("my param");
Si no te importa utilizar una biblioteca de terceros ( Vavr ), puedes escribir
CheckedFunction1<String, Integer> f = this::myMethod;
También tiene la llamada Tríada de prueba que maneja los errores:
Try(() -> f.apply("test")) // results in a Success(Integer) or Failure(Throwable)
.map(i -> ...) // only executed on Success
...
Por favor lea más here .
Descargo de responsabilidad: Soy el creador de Vavr.
Sin embargo, puede crear su propio FunctionalInterface que se lanza como se muestra a continuación.
@FunctionalInterface
public interface UseInstance<T, X extends Throwable> {
void accept(T instance) throws X;
}
luego implementarlo utilizando Lambdas o referencias como se muestra a continuación.
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");
}
}
Tendrá que hacer uno de los siguientes.
Si es su código, defina su propia interfaz funcional que declare la excepción marcada
@FunctionalInterface public interface CheckedFunction<T, R> { R apply(T t) throws IOException; }
y usalo
void foo (CheckedFunction f) { ... }
De lo contrario,
Integer myMethod(String s)
en un método que no declare una excepción comprobada:public Integer myWrappedMethod(String s) { try { return myMethod(s); } catch(IOException e) { throw new UncheckedIOException(e); } }
y entonces
Function<String, Integer> f = (String t) -> myWrappedMethod(t);
o
Function<String, Integer> f = (String t) -> { try { return myMethod(t); } catch(IOException e) { throw new UncheckedIOException(e); } };
Tuve este problema con Class.forName y Class.newInstance dentro de un lambda, así que simplemente hice:
public Object uncheckedNewInstanceForName (String name) {
try {
return Class.forName(name).newInstance();
}
catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
Dentro de la lambda, en lugar de llamar a Class.forName ("myClass"). NewInstance () Acabo de llamar uncheckedNewInstanceForName ("myClass")
Use la Jool Library
o diga la jOOλ library
JOOQ
de JOOQ
. No solo proporciona interfaces manejadas por excepciones sin verificar, sino que también proporciona a la clase Seq muchos métodos útiles.
Además, contiene interfaces funcionales con hasta 16 parámetros. Además, proporciona la clase Tuple que se utiliza en diferentes escenarios.
Específicamente en la búsqueda en la biblioteca para el paquete org.jooq.lambda.fi.util.function
. Contiene todas las interfaces de Java-8 con Checked prepended. Ver abajo para referencia:
Usted puede.
Extendiendo UtilException de UtilException
y agregando <E extends Exception>
cuando sea necesario: de esta manera, el compilador te obligará nuevamente a agregar cláusulas de lanzamiento y todo es como si pudieras lanzar excepciones marcadas de forma nativa en las transmisiones de 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 { }
}
Varias de las soluciones ofrecidas utilizan un argumento genérico de E para pasar el tipo de excepción que se lanza.
Vaya un paso más allá, y en lugar de pasar el tipo de excepción, pase un Consumidor del tipo de excepción, como en ...
Consumer<E extends Exception>
Puede crear varias variaciones reutilizables de Consumer<Exception>
del Consumer<Exception>
que cubrirían las necesidades comunes de manejo de excepciones de su aplicación.
El lenguaje de lanzamiento CheckedException
permite eludir la CheckedException
de la expresión Lambda. CheckedException
una CheckedException
en una CheckedException
RuntimeException
no es bueno para el manejo estricto de errores.
Se puede utilizar como una función de Consumer
utilizada en una colección de Java.
Aquí hay una versión simple y mejorada de la respuesta de 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);
}
}));
}
Esto simplemente envuelve a la lambda en un rebrote . Hace que CheckedException
cualquier Exception
que haya sido lanzada en su lambda.
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;
}
}
Encuentra un código completo y pruebas de unidad here .
Descargo de responsabilidad: no he usado Java 8 todavía, solo lo leí.
Function<String, Integer>
no lanza la IOException
, por lo que no puede poner ningún código en ella que throws IOException
. Si está llamando a un método que espera una Function<String, Integer>
, entonces el lambda que pasa a ese método no puede lanzar IOException
, punto. Puedes escribir un lambda como este (creo que esta es la sintaxis lambda, no estoy seguro):
(String s) -> {
try {
return myMethod(s);
} catch (IOException ex) {
throw new RuntimeException(ex);
// (Or do something else with it...)
}
}
O, si el método al que le está pasando el lambda es uno que escribió usted mismo, puede definir una nueva interfaz funcional y usarla como el tipo de parámetro en lugar de la Function<String, Integer>
:
public interface FunctionThatThrowsIOException<I, O> {
O apply(I input) throws IOException;
}
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();
}
}