Esta questão foi solicitado em um contexto de forEach
.
Comentário (após a resposta foi aceito): Eu aceito a resposta de @nullpointer, mas é o caminho certo apenas no contexto do meu exemplo de código, não na pergunta geral sobre break-capacidade de reduzir ..
A questão:
Mas há uma maneira em reduce
ou em collect
"quebrar" prematuramente, sem passar por todos os elementos de fluxo? (Isso significa que eu preciso acumular o estado, enquanto a iteração, então eu uso reduce
ou collect
).
Em suma: eu preciso iterar todos os elementos do fluxo (elementos são inteiros e ordenou de pequeno a grande), mas olhar para 2 elementos vizinhos e compará-los, se diferença entre eles é maior do que 1, eu preciso de "break" e stop " acumular o estado" e eu preciso retornar o último elemento passado.
Variante de jogar uma RuntimeException
e variante para passar estado externo - ruim para mim.
exemplo de código com os comentários:
public class Solution {
public int solution(int[] A) {
Supplier<int[]> supplier = new Supplier<int[]>() {
@Override
public int[] get() {
//the array describes the accumulated state:
//first element in the array , if set > 0, means - the result is achieved, we can stop iterate over the rest elements
//second element in the array will represent the "previous element" while iterating the stream
return new int[]{0, 0};
}
};
//the array in accumulator describes the accumulated state:
//first element in the array , if set > 0, means - the result is achieved, we can stop iterate over the rest elements
//second element in the array will represent the "previous element" while iterating the stream
ObjIntConsumer<int[]> accumulator = new ObjIntConsumer<int[]>() {
@Override
public void accept(int[] sett, int value) {
if (sett[0] > 0) {
;//do nothing, result is set
} else {
if (sett[1] > 0) {//previous element exists
if (sett[1] + 1 < value) {
sett[0] = sett[1] + 1;
} else {
sett[1] = value;
}
} else {
sett[1] = value;
}
}
}
};
BiConsumer<int[], int[]> combiner = new BiConsumer<int[], int[]>() {
@Override
public void accept(int[] sett1, int[] sett2) {
System.out.println("Combiner is not used, we are in sequence");
}
};
int result[] = Arrays.stream(A).sorted().filter(value -> value > 0).collect(supplier, accumulator, combiner);
return result[0];
}
/**
* We have an input array
* We need order it, filter out all elements that <=0 (to have only positive)
* We need find a first minimal integer that does not exist in the array
* In this example it is 5
* Because 4,6,16,32,67 positive integers array is having 5 like a minimum that not in the array (between 4 and 6)
*
* @param args
*/
public static void main(String[] args) {
int[] a = new int[]{-2, 4, 6, 16, -7, 0, 0, 0, 32, 67};
Solution s = new Solution();
System.out.println("The value is " + s.solution(a));
}
}
Dado um array como entrada, parece-me que você está procurando algo como isto:
int stateStream(int[] arr) {
return IntStream.range(0, arr.length - 1)
.filter(i -> arr[i + 1] - arr[i] > 1) // your condition
.mapToObj(i -> arr[i])
.findFirst() // first such occurrence
.map(i -> i + 1) // to add 1 to the point where the cehck actually failed
.orElse(0); // some default value
}
ou a partir do zero, enquanto você convertê-lo em uma lista de valores classificados e filtrada como:
int stateStream(int[] arr) {
List<Integer> list = Arrays.stream(arr)
.boxed().sorted()
.filter(value -> value > 0)
.collect(Collectors.toList());
return IntStream.range(0, list.size() - 1)
.filter(i -> list.get(i + 1) - list.get(i) > 1)
.mapToObj(list::get)
.findFirst()
.map(i -> i + 1)
.orElse(0);
}