Vejo Vamos ficar com preguiça: Explore o poder real de fluxos de vídeo no youtube (Subramaniam Venkat). (26-30 minutos aproximadamente).
No exemplo, para um ciclo:
List<Integer> numbers = Arrays.asList(1, 2, 3, 5, 4, 6, 7, 8, 9, 10);
int result = 0;
for(int e: values){
if(e > 3 && e % 2 == 0){
result = e * 2;
break;
}
}
Tendo 8 "operações unitárias"
de acordo com o seu exemplo:
public class MainClass {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 5, 4, 6, 7, 8, 9, 10);
System.out.println(
numbers.stream()
.filter(e -> e > 3)
.filter(e -> e % 2 == 0)
.map(e -> e * 2)
.findFirst()
.orElse(0)
);
}
}
este código parece que tem 21 "operações unitárias".
E então ele recomenda usar este código:
public class MainClass {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 5, 4, 6, 7, 8, 9, 10);
System.out.println(
numbers.stream()
.filter(MainClass::isGT3)
.filter(MainClass::isEven)
.map(MainClass::doubleIt)
.findFirst()
.orElse(0)
);
}
private static int doubleIt(Integer e) {
return e * 2;
}
private static boolean isEven(Integer e) {
return e % 2 == 0;
}
private static boolean isGT3(Integer e) {
return e > 3;
}
}
Realmente eu quero entender, como isso pode ser provado que tem 8 operações unitárias em vez de 21 operações unitárias?
Não não não, você entendeu mal a idéia. A ideia é a avaliação preguiçosa em fluxos. E ambos tem "8 cálculos" (usando as palavras dele), ele tentou dizer que parecia que levaria 21.
este
numbers.stream()
.filter(MainClass::isGT3)
.filter(MainClass::isEven)
.map(MainClass::doubleIt)
.findFirst()
.orElse(0)
E
numbers.stream()
.filter(e -> e > 3)
.filter(e -> e % 2 == 0)
.map(e -> e * 2)
.findFirst()
.orElse(0)
São exatamente o mesmo . A única diferença é criar uma função para ser mais legível e isso é tudo. O código imperativo:
List<Integer> numbers = Arrays.asList(1, 2, 3, 5, 4, 6, 7, 8, 9, 10);
int result = 0;
for(int e: values){
if(e > 3 && e % 2 == 0){
result = e * 2;
break;
}
}
eo código nos córregos, calcula exatamente o mesmo, porque eles são chamados na demanda, isso significa que ele não filtra tudo > 3
eo filtro de tudo % 2 == 0
, não, ele combina que as operações, e depois aplicá-lo quando uma função de terminal é chamado ( como findFirst()
)
Como mostra o vídeo, se você colocar algumas impressões entre as funções, ele irá mostrar as operações 8:
public class Main {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 5, 4, 6, 7, 8, 9, 10);
System.out.println(processStream(numbers));
System.out.println(getNumber(numbers));
System.out.println(getNumberEfficient(numbers));
}
static Stream<Integer> processStream(List<Integer> numbers){
return numbers.stream()
.filter(e -> {
System.out.println("GT3: " + e);
return e > 3;
})
.filter(e -> {
System.out.println("is Even: " + e);
return e % 2 == 0;
})
.map(e -> {
System.out.println("times 2: " + e);
return e * 2;
} );
}
static int getNumberEfficient(List<Integer> numbers){
return numbers.stream()
.filter(e -> {
System.out.println("GT3 and even: " + e);
return e > 3 && e % 2 == 0;
})
.map(e -> {
System.out.println("times 2: " + e);
return e * 2;
} )
.findFirst()
.orElse(0);
}
static int getNumber(List<Integer> numbers){
return numbers.stream()
.filter(e -> {
System.out.println("GT3: " + e);
return e > 3;
})
.filter(e -> {
System.out.println("is Even: " + e);
return e % 2 == 0;
})
.map(e -> {
System.out.println("times 2: " + e);
return e * 2;
} )
.findFirst()
.orElse(0);
}
}
ele irá retornar:
Este é o gasoduto, nada foi executado, porque é laze
java.util.stream.ReferencePipeline$3@7ba4f24f
Thees são os 8 operações:
GT3: 1
GT3: 2
GT3: 3
GT3: 5
is Even: 5
GT3: 4
is Even: 4
times 2: 4
8
E isso é um pouco de otimização, em vez de fazer dois filtros, você pode fazer apenas um, e reduzir 8-6:
GT3 and even: 1
GT3 and even: 2
GT3 and even: 3
GT3 and even: 5
GT3 and even: 4
times 2: 4
8