tutorial suma streams procesamiento parte libreria funcional ejemplo datos con java lambda java-8 java-stream

suma - stream java 8 ejemplo



¿Corriente java encontrar coincidencia o la última? (5)

Básicamente, usaría uno de los siguientes dos métodos o desviaciones de los mismos:

Variante de flujo:

<T> T getFirstMatchOrLast(List<T> list, Predicate<T> filter, T defaultValue) { return list.stream() .filter(filter) .findFirst() .orElse(list.isEmpty() ? defaultValue : list.get(list.size() - 1)); }

variante sin flujo:

<T> T getFirstMatchOrLast(Iterable<T> iterable, Predicate<T> filter, T defaultValue) { T relevant = defaultValue; for (T entry : iterable) { relevant = entry; if (filter.test(entry)) break; } return relevant; }

O como también lo sugirió Ilmari Karonen en el comentario con Iterable<T> , entonces puede incluso llamar a stream::iterator en caso de que realmente trate con un Stream lugar de una List . Llamar a los métodos mostrados se vería como sigue:

getFirstMatchOrLast(Arrays.asList(1, 20, 3), i -> i == 20, 1); // returns 20 getFirstMatchOrLast(Collections.emptyList(), i -> i == 3, 20); // returns 20 getFirstMatchOrLast(Arrays.asList(1, 2, 20), i -> i == 7, 30); // returns 20 // only non-stream variant: having a Stream<Integer> stream = Stream.of(1, 2, 20) getFirstMatchOrLast(stream::iterator, i -> i == 7, 30); // returns 20

No usaría reduce aquí porque me suena mal en el sentido de que también pasa por todas las entradas a pesar de que la primera entrada ya podría haber coincidido, es decir, ya no tiene cortocircuito. Además, para mí no es tan legible como filter.findFirst.orElse ... (pero eso es probablemente mi opinión)

Probablemente terminaría con algo como sigue:

<T> Optional<T> getFirstMatchOrLast(Iterable<T> iterable, Predicate<T> filter) { T relevant = null; for (T entry : iterable) { relevant = entry; if (filter.test(entry)) break; } return Optional.ofNullable(relevant); } // or transform the stream variant to somethinng like that... however I think that isn''t as readable anymore...

para que las llamadas se vean como

getFirstMatchOrLast(Arrays.asList(1, 2, 3, 5), i -> i == 7).orElseThrow(...) getFirstMatchOrLast(Arrays.asList(1, 2, 3, 5), i -> i == 7).orElse(0); getFirstMatchOrLast(Arrays.asList(1, 2, 3, 5), i -> i == 7).orElseGet(() -> /* complex formula */); getFirstMatchOrLast(stream::iterator, i -> i == 5).ifPresent(...)

¿Cómo encontrar la primera coincidencia o el último elemento en una lista utilizando el flujo de Java?

Lo que significa que si ningún elemento coincide con la condición, devuelva el último elemento.

p.ej:

OptionalInt i = IntStream.rangeClosed(1,5) .filter(x-> x == 7) .findFirst(); System.out.print(i.getAsInt());

¿Qué debo hacer para que devuelva 5;


Dada la lista

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);

Usted podría simplemente hacer:

int value = list.stream().filter(x -> x == 2) .findFirst() .orElse(list.get(list.size() - 1));

Aquí, si el filtro se evalúa como verdadero, se recupera el elemento, de lo contrario, se devuelve el último elemento del último.

Si la lista está vacía , podría devolver un valor predeterminado, por ejemplo, -1.

int value = list.stream().filter(x -> x == 2) .findFirst() .orElse(list.isEmpty() ? -1 : list.get(list.size() - 1));


No estoy seguro de por qué realmente quieres usar streams para eso, un simple for -loop sería suficiente:

public static <T> T getFirstMatchingOrLast(List<? extends T> source, Predicate<? super T> predicate){ // handle empty case if(source.isEmpty()){ return null; } for(T t : source){ if(predicate.test(t)){ return t; } } return source.get(source.size() -1); }

Que luego se puede llamar como:

Integer match = getFirstMatchingOrLast(ints, i -> i == 7);


Puedes usar la función reduce() así:

OptionalInt i = IntStream.rangeClosed(1, 5) .reduce((first, second) -> first == 7 ? first : second); System.out.print(i.getAsInt());


Si desea hacer esto en una tubería, podría hacer:

int startInc = 1; int endEx = 5; OptionalInt first = IntStream.concat(IntStream.range(startInc, endEx) .filter(x -> x == 7), endEx > 1 ? IntStream.of(endEx) : IntStream.empty()) .findFirst();

pero probablemente sea mejor que recoja los números generados en una lista y luego opere de la siguiente manera:

// first collect the numbers into a list List<Integer> result = IntStream.rangeClosed(startInc,endEx) .boxed() .collect(toList()); // then operate on it int value = result.stream() .filter(x -> x == 7) .findFirst() .orElse(result.get(result.size() - 1));

Alternativamente, si desea que la última devuelva una Opcional vacía en el caso de que la fuente esté vacía (si ese es un escenario posible) en lugar de una excepción, entonces puede hacer:

List<Integer> result = IntStream.rangeClosed(startInc,endEx) .boxed() .collect(toList()); Optional<Integer> first = Stream.concat(result.stream().filter(x -> x == 7), result.isEmpty() ? Stream.empty() : Stream.of(result.get(result.size() - 1))) .findFirst();