Je lis "Java 8 In Action" (par Raoul-Gabriel Urma, Mario Fusco et Alan Mycroft), section 5.6.3, pages 116 et 117. Le code qui est présenté gère le calcul de soi-disant "Triplets de Pythagore". La page 116 montre la première tentative, et la page 117 montre une tentative améliorée de générer ces triplets, où tous deux utilisent la méthode ".rangeClosed()".Flux numériques Exemple d'optimisation
J'ai trouvé quelques optimisations qui vont au-delà du livre et j'aimerais les partager ici. J'ai fait quelques simples calculs "System.currentTimeMillis()" pour voir si mes modifications étaient des améliorations, et elles semblaient être légèrement meilleures que celles trouvées dans le livre. Pouvez-vous fournir de meilleures améliorations, explications ou statistiques pour ce code?
public void test() {
long time1 = System.currentTimeMillis();
/*
* From text, page 116
*/
IntStream.rangeClosed(1, 100).boxed()
.flatMap(a -> IntStream.rangeClosed(a, 100)
.filter(b -> Math.sqrt(a*a + b*b) % 1 == 0)
.mapToObj(b -> new int[]{a, b, (int)Math.sqrt(a*a + b*b)})
)
.forEach(c -> System.out.println("["+c[0]+" "+c[1]+" "+c[2]+"]"));
long time2 = System.currentTimeMillis();
System.out.println();
long time3 = System.currentTimeMillis();
/*
* From text, page 117, I added "map(...)" so that end result are ints, not doubles
*/
IntStream.rangeClosed(1, 100).boxed()
.flatMap(a -> IntStream.rangeClosed(a, 100)
.mapToObj(b -> new double[]{a, b, Math.sqrt(a*a + b*b)})
.filter(t -> t[2] % 1 == 0)
.map(b -> new int[]{(int)b[0], (int)b[1], (int)b[2]})
)
.forEach(c -> System.out.println("["+c[0]+" "+c[1]+" "+c[2]+"]"));
long time4 = System.currentTimeMillis();
System.out.println();
long time5 = System.currentTimeMillis();
/*
* My optimization attempt #1: now mapToObj(...) has c%1!=0 conditional, filter checks array element not null
*/
IntStream.rangeClosed(1, 100).boxed()
.flatMap(a -> IntStream.rangeClosed(a, 100)
.mapToObj(b -> {
double c = Math.sqrt(a*a + b*b);
return new Object[]{a, b, c % 1 == 0 ? (int)c : null};
})
.filter(d -> d[2] != null)
.map(e -> new int[]{(int)e[0], (int)e[1], (int)e[2]})
)
.forEach(f -> System.out.println("["+f[0]+" "+f[1]+" "+f[2]));
long time6 = System.currentTimeMillis();
System.out.println();
long time7 = System.currentTimeMillis();
/*
* My optimization attempt #2: now mapToObj(...) has c%1!=0 conditional, filter checks "array element" not 0
*/
IntStream.rangeClosed(1, 100).boxed()
.flatMap(a -> IntStream.rangeClosed(a, 100)
.mapToObj(b -> {
double c = Math.sqrt(a*a + b*b);
return new int[]{a, b, c % 1 == 0 ? (int)c : 0 };
})
.filter(t -> t[2] != 0)
)
.forEach(d -> System.out.println("["+d[0]+" "+d[1]+" "+d[2]+"]"));
long time8 = System.currentTimeMillis();
System.out.println();
long time9 = System.currentTimeMillis();
/*
* My optimization attempt #3: now mapToObj(...) has c%1!=0 conditional, filter checks "collection element" not null
*/
IntStream.rangeClosed(1, 100).boxed()
.flatMap(a -> IntStream.rangeClosed(a, 100)
.mapToObj(b -> {
double c = Math.sqrt(a*a + b*b);
return (c % 1 != 0) ? null : new int[]{a, b, (int)c};
})
.filter(t -> t != null)
)
.forEach(d -> System.out.println("["+d[0]+" "+d[1]+" "+d[2]+"]"));
long time10 = System.currentTimeMillis();
System.out.println();
long timeDelta1 = time2 - time1;
long timeDelta2 = time4 - time3;
long timeDelta3 = time6 - time5;
long timeDelta4 = time8 - time7;
long timeDelta5 = time10 - time9;
System.out.println("timeDelta1: " + timeDelta1 + ", timeDelta2: " + timeDelta2 + ", timeDelta3: " + timeDelta3 + ", timeDelta4: " + timeDelta4 + ", timeDelta5: " + timeDelta5);
}
public static void main(String[] args){
ReduceTest reduceTest = new ReduceTest();
reduceTest.test();
}
REMARQUE: Il semble que vous pouvez utiliser "return;" dans une méthode ".forEach()", mais pas dans une méthode ".mapToInt()". En utilisant "retour" dans le lambda passé dans la méthode ".mapToInt()" supprimerait le besoin d'avoir la méthode ".filter()". Il semble que ce serait une amélioration pour les cours d'api.
Je pense que cette question est discutée à mieux: http://codereview.stackexchange.com/ – Flown
@Flown, bon point, je l'ai fait. –
@Alexis, merci, cette balise stream devrait plutôt être java-stream, vous avez bien sûr raison. –