API Stream ajoutée dans Java 8. J'ai fait des recherches et utilisé le minimum au besoin, mais je ne l'ai pas bien compris, alors j'ai réexaminé et essayé.
"Une classe qui prend en charge les opérations fonctionnelles sur un flux d'éléments". https://docs.oracle.com/javase/jp/8/docs/api/java/util/stream/package-summary.html … Le document officiel est difficile à lire, probablement parce qu'il s'agit d'une traduction automatique. Vous pouvez comprendre qui a lu l'anglais ...
L '"élément" semble ici se référer principalement à des éléments de collection tels que List. Stream est exactement comme il est écrit dans cet article. https://qiita.com/castaneai/items/3dbdd8543b020aa903cb
Mon interprétation est
--Facile à utiliser sur les éléments de la collection
J'ai senti que JavaDoc pour l'interface Stream serait la base de tout, donc je vais me concentrer ici. https://docs.oracle.com/javase/jp/8/docs/api/java/util/stream/Stream.html
Les éléments dérivés tels que les méthodes qui renvoient IntStream sont exclus.
J'ai créé un bean et une méthode pour créer des données de test. Je l'appelle à partir de la méthode principale, crée une variable appelée liste, puis expérimente.
Bean
public class TestBean {
String key;
String value;
String description;
public TestBean(String key, String value, String description) {
this.setKey(key);
this.setValue(value);
this.setDescription(description);
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@Override
public String toString() {
return "key:" + this.key + " value:" + this.value + " description:" + this.description;
}
}
Méthode de création des données de test
private static List<TestBean> editTestData() {
List<TestBean> list = new ArrayList<>();
list.add(new TestBean("B", "Butaman", "Contient du porc"));
list.add(new TestBean("A", "Anman", "Contient anko"));
list.add(new TestBean("C", "Chukaman", "C'est un terme général pour Anmanbutaman etc."));
return list;
}
filter Comme son nom l'indique, il a filtré!
filter
list.stream()
.filter(x -> x.getValue().equals("Anman"))
.forEach(x -> System.out.println(x.getDescription()));
Résultat d'exécution
Contient anko
map Je l'ai interprété comme la création d'un autre Stream basé sur le Stream. Dans cet exemple, un Stream configuré avec le type TestBean est remplacé par un Stream configuré avec une String.
map
list.stream()
.map(x -> x.getKey() + x.getValue() + x.getDescription())
.forEach(x -> System.out.println(x));
Résultat d'exécution
B Butaman contient du porc
Un Anman Anko est inclus
C Chukaman Anmanbutaman etc.
flatMap Il semble que vous puissiez créer un Stream dans un Stream. Une image comme faire un tableau avec Stream? Ici, chaque élément du Bean qui constitue une ligne est séparé pour créer un autre Stream.
flatMap
list.stream()
.flatMap(x -> Stream.of(Arrays.asList(x.getKey(),x.getValue(),x.getDescription())))
.forEach(x -> x.forEach(y -> System.out.println(y)));
Résultat d'exécution
B
Butaman
Contient du porc
A
Anman
Contient anko
C
Chukaman
C'est un terme général pour Anmanbutaman etc.
distinct Éliminez les éléments en double. En effectuant ce test, nous avons gonflé les données de test ci-dessus.
<détails> <détails> <détails> <résumé> avec </ résumé> sorted
Trier comme son nom l'indique.
Dans cet exemple, les éléments nommés key (ABC) sont triés dans l'ordre. peek
Cela ne manipule pas spécifiquement le contenu du flux,
Cela ressemble à une méthode de débogage.
peek = Un aperçu (traduit littéralement) Je me demandais si forEach serait fait après que tous les aperçus aient été faits en premier, mais il semble que le traitement intermédiaire → le traitement de fin soit fait pour chaque élément. limit
Tronquez le nombre de flux au nombre spécifié. skip
Contrairement à la limite, il saute le début de Stream. forEach
Je l'ai utilisé avec désinvolture à chaque fois jusqu'à présent.
Traite tous les éléments de Stream.
… Mais il semble que la commande ne soit pas garantie. Uniquement pour les flux parallèles? forEachOrdered
C'est la même chose que forEach, mais il semble que la commande soit garantie en utilisant ceci. toArray
Faites simplement du flux un tableau. reduce
réduire = réduire, réduire (littéralement)
Cela semble utile lors de l'agrégation du contenu de Stream.
Dans cet exemple, l'élément nommé value est attaché.
Un seul facultatif est renvoyé par Stream.
En outre, il existe également une réduction qui peut définir la valeur initiale. Différence de signature. collect
Il semble être utilisé lorsque vous souhaitez le renvoyer en tant que collection au lieu d'un seul élément comme facultatif.
Collection → Modifier en tant que flux → Sortie en tant que collection
Je pense que je l'utilise assez souvent. Si vous souhaitez implémenter sérieusement les différentes interfaces qui sont les arguments de collect par vous-même, vous devez écrire environ 5 méthodes abstraites, il est donc facile d'utiliser la méthode statique fournie dans la classe Collectors. min
Comme son nom l'indique, il renvoie le plus petit comme facultatif.
Le minimum est le même que pour le tri, et le comparateur est implémenté et défini.
Dans cet exemple, spécifiez l'élément appelé key. max
Le contraire de min! count
Comme son nom l'indique, il renvoie le nombre d'éléments Stream. anyMatch
Comme je l'ai lu, il renvoie vrai si l'une des conditions de Stream est remplie.
Dans cet exemple, nous recherchons un élément avec la clé "A". allMatch
Tant que vous ne lirez pas ceci également, il renvoie true si tous les éléments du Stream remplissent les conditions spécifiées. noneMatch
Renvoie true s'il n'y a rien de tel dans le Stream. findFirst
Comme son nom l'indique, il renvoie le premier! findAny
Il passe par son nom et renvoie quelque chose.
Je parle de quelque chose ...
Je ne sais pas vraiment ce qui sera retourné. Vous ne pouvez pas spécifier d'argument.
Quand je l'ai essayé avec un flux séquentiel, le premier élément a été renvoyé, mais il semble qu'il n'y ait aucune garantie.
(2018/12/08 j'ai reçu un commentaire et l'ai corrigé) J'ai écrasé l'élément de valeur du bean dans le flux avec une chaîne fixe.
La source (List) n'a certainement pas changé. <détails> <détails> Créer une liste de 150 millions
Stockez des nombres aléatoires de 0 à 99 dedans
Créez une autre liste en extrayant uniquement les éléments qui stockent 99
J'ai fait un processus inutile et je l'ai mesuré. En conséquence, il n'y a pas de grande différence entre List et stream,
paralellStream était évidemment rapide. <détails> <détails> Ce n'était certainement pas garanti avec parallelStream.
Dans Sequential Stream, il a été accédé dans l'ordre de la source d'origine (Liste). <détails> <détails> Il passe une interface fonctionnelle (comportement) comme argument au lieu de données.
C'est ce qu'on appelle la programmation fonctionnelle.
Je ne pouvais pas l'écrire facilement parce que je ne l'ai écrit que de manière procédurale. Je l'oublie bientôt et je ne peux pas l'écrire d'un seul coup, donc au lieu d'utiliser une expression lambda, j'ai créé une classe anonyme avec une nouvelle interface () {...}, implémenté une méthode abstraite et l'ai remplacée par une expression lambda. ..
J'ai honte de dire ...
Eh bien, vous vous y habituerez bientôt. Merci à tous les auteurs! Principes de base de l'API Stream
https://qiita.com/Takmiy/items/f1d44dfde0d3a906d321 Enquête sur la fonction Java 8, consommateur, fournisseur, prédicat
https://qiita.com/subaru44k/items/c55d9b9fc419f0d09c64 Qu'est-ce que la programmation fonctionnelle et qu'est-ce que lambda?
https://qiita.com/lrf141/items/98ffbeaee42d30cca4dc Différence entre Stream map et flatMap
https://qiita.com/KevinFQ/items/97137efb2159009b60e1 En dehors de Qiita. Il décrit le but de l'API Stream jusqu'aux résultats expérimentaux.
http://d.hatena.ne.jp/nowokay/20130506
Recommended Posts
Données de test (dupliquer a)
private static List<TestBean> editTestData() {
List<TestBean> list = new ArrayList<>();
TestBean a = new TestBean("A", "Anman", "Contient anko");
TestBean b = new TestBean("B", "Butaman", "Contient du porc");
TestBean c = new TestBean("C", "Chukaman", "C'est un terme général pour Anmanbutaman etc.");
list.add(b);
list.add(a);
list.add(a);
list.add(a);
list.add(c);
return list;
}
La source
list.stream()
.forEach(x -> System.out.println(x.getDescription()));
Résultat d'exécution
Contient du porc
Contient anko
Contient anko
Contient anko
C'est un terme général pour Anmanbutaman etc.
La source
list.stream()
.distinct()
.forEach(x -> System.out.println(x.getDescription()));
Résultat d'exécution
Contient du porc
Contient anko
C'est un terme général pour Anmanbutaman etc.
sorted
list.stream()
.sorted((o1, o2) -> o1.getKey().compareTo(o2.getKey()))
.forEach(x -> System.out.println(x.getKey() + x.getValue() + x.getDescription()));
Résultat d'exécution
Un Anman Anko est inclus
B Butaman contient du porc
C Chukaman Anmanbutaman etc.
peek
list.stream()
.peek(x -> System.out.println(x))
.forEach(x -> System.out.println("Sortie avec forEach"));
Résultat d'exécution
key:B value:Description du butaman:Contient du porc
Sortie avec forEach
key:A value:Description d'Anman:Contient anko
Sortie avec forEach
key:C value:Description de Chukaman:C'est un terme général pour Anmanbutaman etc.
Sortie avec forEach
limit
list.stream()
.limit(2)
.forEach(x -> System.out.println(x));
Résultat d'exécution
key:B value:Description du butaman:Contient du porc
key:A value:Description d'Anman:Contient anko
skip
list.stream()
.skip(1)
.forEach(x -> System.out.println(x));
Résultat d'exécution
key:A value:Description d'Anman:Contient anko
key:C value:Description de Chukaman:C'est un terme général pour Anmanbutaman etc.
Opération de terminaison
toArray
Object[] testBeans = list.stream().toArray();
System.out.println(testBeans[0].toString());
System.out.println(testBeans[1].toString());
Résultat d'exécution
key:B value:Description du butaman:Contient du porc
key:A value:Description d'Anman:Contient anko
reduce
Optional<TestBean> opt = list.stream()
.reduce((t, u) -> {
t.setValue(t.getValue() + u.getValue());
return t;
});
System.out.println(opt.orElse(new TestBean("x", "x", "x")));
Résultat d'exécution
key:B value:Description de Butaman Anman Chukaman:Contient du porc
collect
List<TestBean> newlist = list.stream()
.filter(x -> x.getKey().equals("C"))
.collect(Collectors.toList());
System.out.println(newlist.get(0).toString());
Résultat d'exécution
key:C value:Description de Chukaman:C'est un terme général pour Anmanbutaman etc.
min
Optional<TestBean> op = list.stream()
.min((x, y) -> x.getKey().compareTo(y.getKey()));
System.out.println(op.orElse(new TestBean("x", "x", "x")).toString());
Résultat d'exécution
key:A value:Description d'Anman:Contient anko
max
Optional<TestBean> op = list.stream()
.max((x, y) -> x.getKey().compareTo(y.getKey()));
System.out.println(op.orElse(new TestBean("x", "x", "x")).toString());
Résultat d'exécution
key:C value:Description de Chukaman:C'est un terme général pour Anmanbutaman etc.
count
System.out.println(list.stream().count());
Résultat d'exécution
3
anyMatch
boolean matched = list.stream().anyMatch(x -> x.getKey().equals("A"));
if (matched) {
System.out.println("Il y avait un homme!");
}
Résultat d'exécution
Il y avait un homme!
allMatch
boolean matched = list.stream().allMatch(x -> !x.getKey().equals("Z"));
if (matched) {
System.out.println("Tout le monde n'est pas Z!");
}
Résultat d'exécution
Tout le monde n'est pas Z!
noneMatch
boolean noMatched = list.stream().noneMatch(x -> x.getKey().equals("Z"));
if (noMatched) {
System.out.println("Il n'y avait pas de guerrier Z");
}
Résultat d'exécution
Il n'y avait pas de guerrier Z
findFirst
Optional<TestBean> op = list.stream().findFirst();
System.out.println(op.orElse(new TestBean("x", "x", "x")).toString());
Résultat d'exécution
key:B value:Description du butaman:Contient du porc
findAny
Optional<TestBean> op = list.stream().findAny();
System.out.println(op.orElse(new TestBean("x", "x", "x")).toString());
Résultat d'exécution
key:B value:Description du butaman:Contient du porc
Expériences autres que la méthode
Vérifiez que la source d'origine n'a pas changé même si vous utilisez Stream
python
System.out.println("【Changer avant】");
for (TestBean bean : list) {
System.out.println(bean);
}
list.stream().map(x -> {
x.setValue("Je l'ai changé!");
return x;
});
System.out.println("[Après le changement]");
for (TestBean bean : list) {
System.out.println(bean);
}
Résultat d'exécution
【Changer avant】
key:B value:Description du butaman:Contient du porc
key:A value:Description d'Anman:Contient anko
key:C value:Description de Chukaman:C'est un terme général pour Anmanbutaman etc.
[Après le changement]
key:B value:Description du butaman:Contient du porc
key:A value:Description d'Anman:Contient anko
key:C value:Description de Chukaman:C'est un terme général pour Anmanbutaman etc.
Mesurer la différence de vitesse
python
final int loopsize = 150000000;
final int randomrange = 100;
final int findnum = 99;
// create many data
System.out.println("Pendant la génération des données de test...");
List<Integer> list = IntStream.range(0, loopsize)
.mapToObj(x -> new Random().nextInt(randomrange))
.collect(Collectors.toList());
// byList
LocalDateTime starttime = start("--- byList ---");
List<Integer> newlist = new ArrayList<>();
for (Integer i : list) {
if (i.intValue() == findnum) {
newlist.add(i);
}
}
end(starttime, findnum, newlist);
// byStream
starttime = start("--- byStream ---");
List<Integer> streamlist = list.stream()
.filter(x -> x.intValue() == findnum).collect(Collectors.toList());
end(starttime, findnum, streamlist);
// byParalellStream
starttime = start("--- byParalellStream ---");
List<Integer> paralellStreamlist = list.parallelStream()
.filter(x -> x.intValue() == findnum).collect(Collectors.toList());
end(starttime, findnum, paralellStreamlist);
}
private static LocalDateTime start(String msg) {
System.out.println("");
System.out.println(msg);
LocalDateTime ldt = LocalDateTime.now();
System.out.println("start: " + ldt);
return ldt;
}
private static void end(LocalDateTime starttime, int findnum,
List<Integer> newlist) {
LocalDateTime elapsed = LocalDateTime.now();
System.out.println("end : " + elapsed);
elapsed = elapsed.minusHours(starttime.getHour());
elapsed = elapsed.minusMinutes(starttime.getMinute());
elapsed = elapsed.minusSeconds(starttime.getSecond());
elapsed = elapsed.minusNanos(starttime.getNano());
System.out
.println("elapsed: " + elapsed.format(DateTimeFormatter.ISO_TIME));
System.out.println(findnum + "Est" + newlist.size() + "Il y en avait un!");
}
Résultat d'exécution
Pendant la génération des données de test...
--- byList ---
start: 2018-12-08T15:35:51.584
end : 2018-12-08T15:35:52.039
elapsed: 00:00:00.455
Il y en avait 1500072 99!
--- byStream ---
start: 2018-12-08T15:35:52.052
end : 2018-12-08T15:35:52.450
elapsed: 00:00:00.398
Il y en avait 1500072 99!
--- byParalellStream ---
start: 2018-12-08T15:35:52.450
end : 2018-12-08T15:35:52.672
elapsed: 00:00:00.222
Il y en avait 1500072 99!
Confirmez que l'ordre de forEach et findAny n'est pas garanti
python
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
System.out.println("--- byList ---");
for (int i : list) {
System.out.println(i);
}
System.out.println("--- byStream ---");
list.stream().forEach(i -> System.out.println(i));
System.out.println("--- byParallelStream ---");
list.parallelStream().forEach(i -> System.out.println(i));
System.out
.println("findany by stream:" + list.stream().findAny().orElse(null));
System.out.println("findany by parallelStream:"
+ list.parallelStream().findAny().orElse(null));
Résultat d'exécution
--- byList ---
1
2
3
4
5
6
7
8
9
10
--- byStream ---
1
2
3
4
5
6
7
8
9
10
--- byParallelStream ---
7
9
6
3
5
2
10
1
4
8
findany by stream:1
findany by parallelStream:7
Point confus
Arguments pour chaque méthode dans l'interface Stream
Articles que j'ai utilisés comme référence