Maison  >  Article  >  Java  >  Résumé de l'utilisation détaillée de Stream en Java8

Résumé de l'utilisation détaillée de Stream en Java8

WBOY
WBOYavant
2022-10-05 09:00:272247parcourir

Cet article vous apporte des connaissances pertinentes sur Java, qui présentent principalement des problèmes liés à l'utilisation détaillée de Stream. Le nouveau Stream dans la version, ainsi que le Lambda qui apparaît dans la même version, nous offrent un excellent moyen d'exploiter les collections ( Collection). Très pratique, jetons-y un coup d'œil ci-dessous, j'espère que cela sera utile à tout le monde.

Résumé de l'utilisation détaillée de Stream en Java8

Etude recommandée : "Tutoriel vidéo Java"

1. Présentation

Java 8 est une version très réussie Le nouveau Stream de cette version, combiné au Lambda qui apparaît dans la même version, nous donne. un ensemble d'opérations ( Collection) offre une grande commodité. Stream est un nouveau membre du JDK8, qui permet le traitement des collections de données de manière déclarative. Le flux Stream peut être considéré comme un itérateur avancé pour parcourir la collection de données. Stream est le concept abstrait clé pour le traitement des collections dans Java 8. Il peut spécifier les opérations que vous souhaitez effectuer sur la collection et effectuer des opérations très complexes telles que la recherche/filtrage/filtrage, le tri, l'agrégation et le mappage des données. L'utilisation de l'API Stream pour opérer sur les données de collecte est similaire à l'utilisation de SQL pour effectuer des requêtes de base de données. Vous pouvez également utiliser l'API Stream pour effectuer des opérations en parallèle. En bref, l'API Stream offre un moyen efficace et facile à utiliser de traiter les données.

1. Avantages de l'utilisation de streams

Le code est écrit de manière déclarative, décrivant ce qu'il veut accomplir, plutôt que comment accomplir une opération.
Plusieurs opérations de base peuvent être connectées pour exprimer des pipelines de traitement de données complexes tout en gardant le code clair et lisible.

2. Qu'est-ce qu'un flux ?

Génère une séquence d'éléments à partir d'une source qui prend en charge les opérations de traitement de données. La source de données peut être une collection, un tableau ou une ressource IO.

D'un point de vue opérationnel, les flux sont différents des collections. Les flux ne stockent pas de valeurs de données ; le but des flux est de traiter les données, il s'agit d'algorithmes et de calculs.

Si vous utilisez une collection comme source de données d'un flux, la création du flux ne provoquera pas le flux de données ; si l'opération de terminaison du flux nécessite une valeur, le flux obtiendra uniquement la valeur de la collection ; utilisé une fois.

L'idée centrale des flux est de retarder le calcul, et les flux ne calculent les valeurs que lorsque cela est nécessaire.
Résumé de lutilisation détaillée de Stream en Java8
Le flux peut être créé à partir d'un tableau ou d'une collection. Les opérations sur les flux sont divisées en deux types :

Opérations intermédiaires, à chaque fois qu'un nouveau flux est renvoyé, il peut y en avoir plusieurs.

Opération de terminal, chaque flux ne peut effectuer qu'une seule opération de terminal et le flux ne peut pas être réutilisé une fois l'opération de terminal terminée. Les opérations du terminal produisent une nouvelle collection ou valeur.

Caractéristiques :

n'est pas une structure de données et ne sauvegardera pas les données.

Il ne modifiera pas la source de données d'origine, il enregistrera les données exploitées dans un autre objet. (Réservation : après tout, la méthode peek peut modifier les éléments du flux)

Évaluation paresseuse Lors du traitement intermédiaire du flux, l'opération est uniquement enregistrée et ne sera pas exécutée immédiatement. Elle doit attendre l'opération de terminaison. est effectué avant que l'opération proprement dite soit effectuée.

2. Classification

Résumé de lutilisation détaillée de Stream en Java8

Stateless : signifie que le traitement des éléments n'est pas affecté par les éléments précédents ;

Stateful : signifie que l'opération ne peut continuer qu'après avoir obtenu tous les éléments ;

Fonctionnement sans court-circuit : signifie que tous les éléments doivent être traités pour obtenir le résultat final

Fonctionnement en court-circuit : signifie que le résultat final peut être obtenu lorsque certains éléments répondant aux conditions sont rencontrés, comme A ; || B. Tant que A est vrai, aucun jugement n'est requis. Le résultat de B.

3. Création de Stream

Le flux peut être créé via un tableau de collection.

1. Utilisez la méthode java.util.Collection.stream() pour créer un flux avec une collection

List<string> list = Arrays.asList("a", "b", "c");// 创建一个顺序流
Stream<string> stream = list.stream();// 创建一个并行流
Stream<string> parallelStream = list.parallelStream();</string></string></string>

2 Utilisez la méthode java.util.Arrays.stream(T[]array) pour créer un flux avec un. array

int[] array={1,3,5,6,8};IntStream stream = Arrays.stream(array);

3. Utilisez des méthodes Stream Static : of(), iterate(), generate()

Stream<integer> stream = Stream.of(1, 2, 3, 4, 5, 6);
 Stream<integer> stream2 = Stream.iterate(0, (x) -> x + 3).limit(4);stream2.forEach(System.out::println);
 Stream<double> stream3 = Stream.generate(Math::random).limit(3);stream3.forEach(System.out::println);</double></integer></integer>

Résultats de sortie :

0 3 6 90.67961569092719940.19143142088542830.8116932592396652

Une distinction simple entre stream et parallelStream : stream est un flux séquentiel et le thread principal. effectue des opérations sur le flux en séquence, tandis que parallelStream est un flux parallèle, exploite en interne le flux de manière multithread en exécution parallèle, mais le principe est qu'il n'y a aucune exigence d'ordre pour le traitement des données dans le flux. Par exemple, en filtrant les nombres impairs dans une collection, la différence de traitement entre les deux est la suivante :
Résumé de lutilisation détaillée de Stream en Java8
Si la quantité de données dans le flux est suffisamment importante, les flux parallèles peuvent accélérer le traitement.

En plus de créer directement des flux parallèles, vous pouvez également convertir des flux séquentiels en flux parallèles via parallel() :

Optional<integer> findFirst = list.stream().parallel().filter(x->x>6).findFirst();</integer>

IV Introduction à l'API Stream

在这里插入Résumé de lutilisation détaillée de Stream en Java8描述
Résumé de lutilisation détaillée de Stream en Java8

先贴上几个案例,水平高超的同学可以挑战一下:从员工集合中筛选出salary大于8000的员工,并放置到新的集合里。统计员工的最高薪资、平均薪资、薪资之和。将员工按薪资从高到低排序,同样薪资者年龄小者在前。将员工按性别分类,将员工按性别和地区分类,将员工按薪资是否高于8000分为两部分。用传统的迭代处理也不是很难,但代码就显得冗余了,跟Stream相比高下立判。

Prérequis : Classe d'employés

static List<person> personList = new ArrayList<person>();private static void initPerson() {
    personList.add(new Person("张三", 8, 3000));
    personList.add(new Person("李四", 18, 5000));
    personList.add(new Person("王五", 28, 7000));
    personList.add(new Person("孙六", 38, 9000));}</person></person>

1. . Traversal/ Matching (foreach/find/match)

Stream prend également en charge les éléments de parcours et de correspondance de type collection, sauf que les éléments du Stream existent en tant que types facultatifs. La traversée et la correspondance des flux sont très simples.

// import已省略,请自行添加,后面代码亦是
 
public class StreamTest {
  public static void main(String[] args) {
        List<integer> list = Arrays.asList(7, 6, 9, 3, 8, 2, 1);
 
        // 遍历输出符合条件的元素
        list.stream().filter(x -> x > 6).forEach(System.out::println);
        // 匹配第一个
        Optional<integer> findFirst = list.stream().filter(x -> x > 6).findFirst();
        // 匹配任意(适用于并行流)
        Optional<integer> findAny = list.parallelStream().filter(x -> x > 6).findAny();
        // 是否包含符合特定条件的元素
        boolean anyMatch = list.stream().anyMatch(x -> x <h3>2、按条件匹配filter</h3>
<p><img src="https://img.php.cn/upload/article/000/000/067/c32799257ddfee7ae65dfaf7bce4b27c-5.png" alt="在这里插入Résumé de lutilisation détaillée de Stream en Java8描述"></p>
<p><strong>(1)筛选员工中已满18周岁的人,并形成新的集合</strong></p>
<pre class="brush:php;toolbar:false">/**
 * 筛选员工中已满18周岁的人,并形成新的集合
 * @思路
 * List<person> list = new ArrayList<person>();
 * for(Person person : personList) {
 *     if(person.getAge() >= 18) {
 *          list.add(person);
 *     }
 * }
 */
private static void filter01() {
    initPerson();
    List<person> collect = personList.stream().filter(x -> x.getAge()>=18).collect(Collectors.toList());
    System.out.println(collect);}</person></person></person>

在这里插入Résumé de lutilisation détaillée de Stream en Java8描述
(2)自定义条件匹配
Résumé de lutilisation détaillée de Stream en Java8

3、聚合max、min、count

Résumé de lutilisation détaillée de Stream en Java8

(1)获取String集合中最长的元素

/**
 * 获取String集合中最长的元素
 * @思路
 * List<string> list = Arrays.asList("zhangsan", "lisi", "wangwu", "sunliu");
 * String max = "";
 * int length = 0;
 * int tempLength = 0;
 * for(String str : list) {
 *     tempLength = str.length();
 *     if(tempLength > length) {
 *         length  = str.length();
 *         max = str;
 *      }
 * }
 * @return zhangsan
 */
private static void test02() {
    List<string> list = Arrays.asList("zhangsan", "lisi", "wangwu", "sunliu");
    Comparator super String> comparator = Comparator.comparing(String::length);
    Optional<string> max = list.stream().max(comparator);
    System.out.println(max);}</string></string></string>

Résumé de lutilisation détaillée de Stream en Java8
(2)获取Integer集合中的最大值

//获取Integer集合中的最大值
private static void test05() {
    List<integer> list = Arrays.asList(1, 17, 27, 7);
    Optional<integer> max = list.stream().max(Integer::compareTo);
    // 自定义排序
    Optional<integer> max2 = list.stream().max(new Comparator<integer>() {
        @Override
        public int compare(Integer o1, Integer o2) {
            return o1.compareTo(o2);
        }
    });
    System.out.println(max2);}</integer></integer></integer></integer>

Résumé de lutilisation détaillée de Stream en Java8

//获取员工中年龄最大的人
private static void test06() {
    initPerson();
    Comparator super Person> comparator = Comparator.comparingInt(Person::getAge);
    Optional<person> max = personList.stream().max(comparator);
    System.out.println(max);}</person>

(3)获取员工中年龄最大的人
在这里插入Résumé de lutilisation détaillée de Stream en Java8描述
4)计算integer集合中大于10的元素的个数
在这里插入Résumé de lutilisation détaillée de Stream en Java8描述

4、map与flatMap

map:接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。

flatMap:接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。

Résumé de lutilisation détaillée de Stream en Java8

(1)字符串大写
Résumé de lutilisation détaillée de Stream en Java8
(2)整数数组每个元素+3

/**
 * 整数数组每个元素+3
 * @思路
 * List<integer> list = Arrays.asList(1, 17, 27, 7);
   List<integer> list2 = new ArrayList<integer>();
   for(Integer num : list) {
      list2.add(num + 3);
   }
   @return [4, 20, 30, 10]
 */
private static void test09() {
    List<integer> list = Arrays.asList(1, 17, 27, 7);
    List<integer> collect = list.stream().map(x -> x + 3).collect(Collectors.toList());
    System.out.println(collect);}</integer></integer></integer></integer></integer>

(3)公司效益好,每人涨2000

/**
 * 公司效益好,每人涨2000
 *
 */
private static void test10() {
    initPerson();
    List<person> collect = personList.stream().map(x -> {
        x.setAge(x.getSalary()+2000);
        return x;
    }).collect(Collectors.toList());
    System.out.println(collect);}</person>

(4)将两个字符数组合并成一个新的字符数组

/**
 * 将两个字符数组合并成一个新的字符数组
 *
 */
private static void test11() {
    String[] arr = {"z, h, a, n, g", "s, a, n"};
    List<string> list = Arrays.asList(arr);
    System.out.println(list);
    List<string> collect = list.stream().flatMap(x -> {
        String[] array = x.split(",");
        Stream<string> stream = Arrays.stream(array);
        return stream;
    }).collect(Collectors.toList());
    System.out.println(collect);}</string></string></string>

(5)将两个字符数组合并成一个新的字符数组

/**
 * 将两个字符数组合并成一个新的字符数组
 * @return [z,  h,  a,  n,  g, s,  a,  n]
 */
private static void test11() {
    String[] arr = {"z, h, a, n, g", "s, a, n"};
    List<string> list = Arrays.asList(arr);
    List<string> collect = list.stream().flatMap(x -> {
        String[] array = x.split(",");
        Stream<string> stream = Arrays.stream(array);
        return stream;
    }).collect(Collectors.toList());
    System.out.println(collect);}</string></string></string>

5、规约reduce

归约,也称缩减,顾名思义,是把一个流缩减成一个值,能实现对集合求和、求乘积和求最值操作。
Résumé de lutilisation détaillée de Stream en Java8
(1)求Integer集合的元素之和、乘积和最大值

/**
 * 求Integer集合的元素之和、乘积和最大值
 *
 */
private static void test13() {
    List<integer> list = Arrays.asList(1, 2, 3, 4);
    //求和
    Optional<integer> reduce = list.stream().reduce((x,y) -> x+ y);
    System.out.println("求和:"+reduce);
    //求积
    Optional<integer> reduce2 = list.stream().reduce((x,y) -> x * y);
    System.out.println("求积:"+reduce2);
    //求最大值
    Optional<integer> reduce3 = list.stream().reduce((x,y) -> x>y?x:y);
    System.out.println("求最大值:"+reduce3);}</integer></integer></integer></integer>

(2)求所有员工的工资之和和最高工资

/*
 * 求所有员工的工资之和和最高工资
 */
private static void test14() {
    initPerson();
    Optional<integer> reduce = personList.stream().map(Person :: getSalary).reduce(Integer::sum);
    Optional<integer> reduce2 = personList.stream().map(Person :: getSalary).reduce(Integer::max);
    System.out.println("工资之和:"+reduce);
    System.out.println("最高工资:"+reduce2);}</integer></integer>

6、收集(toList、toSet、toMap)

取出大于18岁的员工转为map

/**
 * 取出大于18岁的员工转为map
 *
 */
private static void test15() {
    initPerson();
    Map<string> collect = personList.stream().filter(x -> x.getAge() > 18).collect(Collectors.toMap(Person::getName, y -> y));
    System.out.println(collect);}</string>

7、collect

Collectors提供了一系列用于数据统计的静态方法:

计数: count

平均值: averagingInt、 averagingLong、 averagingDouble

最值: maxBy、 minBy

求和: summingInt、 summingLong、 summingDouble

统计以上所有: summarizingInt、 summarizingLong、 summarizingDouble

/**
 * 统计员工人数、平均工资、工资总额、最高工资
 */
private static void test01(){
    //统计员工人数
    Long count = personList.stream().collect(Collectors.counting());
    //求平均工资
    Double average = personList.stream().collect(Collectors.averagingDouble(Person::getSalary));
    //求最高工资
    Optional<integer> max = personList.stream().map(Person::getSalary).collect(Collectors.maxBy(Integer::compare));
    //求工资之和
    Integer sum = personList.stream().collect(Collectors.summingInt(Person::getSalary));
    //一次性统计所有信息
    DoubleSummaryStatistics collect = personList.stream().collect(Collectors.summarizingDouble(Person::getSalary));
    System.out.println("统计员工人数:"+count);
    System.out.println("求平均工资:"+average);
    System.out.println("求最高工资:"+max);
    System.out.println("求工资之和:"+sum);
    System.out.println("一次性统计所有信息:"+collect);}</integer>

8、分组(partitioningBy/groupingBy)

分区:将stream按条件分为两个 Map,比如员工按薪资是否高于8000分为两部分。

分组:将集合分为多个Map,比如员工按性别分组。有单级分组和多级分组。
Résumé de lutilisation détaillée de Stream en Java8

将员工按薪资是否高于8000分为两部分;将员工按性别和地区分组

public class StreamTest {
  public static void main(String[] args) {
    personList.add(new Person("zhangsan",25, 3000, "male", "tieling"));
        personList.add(new Person("lisi",27, 5000, "male", "tieling"));
        personList.add(new Person("wangwu",29, 7000, "female", "tieling"));
        personList.add(new Person("sunliu",26, 3000, "female", "dalian"));
        personList.add(new Person("yinqi",27, 5000, "male", "dalian"));
        personList.add(new Person("guba",21, 7000, "female", "dalian"));
 
    // 将员工按薪资是否高于8000分组
        Map<boolean>> part = personList.stream().collect(Collectors.partitioningBy(x -> x.getSalary() > 8000));
        // 将员工按性别分组
        Map<string>> group = personList.stream().collect(Collectors.groupingBy(Person::getSex));
        // 将员工先按性别分组,再按地区分组
        Map<string>>> group2 = personList.stream().collect(Collectors.groupingBy(Person::getSex, Collectors.groupingBy(Person::getArea)));
        System.out.println("员工按薪资是否大于8000分组情况:" + part);
        System.out.println("员工按性别分组情况:" + group);
        System.out.println("员工按性别、地区:" + group2);
  }}</string></string></boolean>

9、连接joining

joining可以将stream中的元素用特定的连接符(没有的话,则直接连接)连接成一个字符串。
Résumé de lutilisation détaillée de Stream en Java8

10、排序sorted

将员工按工资由高到低(工资一样则按年龄由大到小)排序

private static void test04(){
    // 按工资升序排序(自然排序)
    List<string> newList = personList.stream().sorted(Comparator.comparing(Person::getSalary)).map(Person::getName)
            .collect(Collectors.toList());
    // 按工资倒序排序
    List<string> newList2 = personList.stream().sorted(Comparator.comparing(Person::getSalary).reversed())
            .map(Person::getName).collect(Collectors.toList());
    // 先按工资再按年龄升序排序
    List<string> newList3 = personList.stream()
            .sorted(Comparator.comparing(Person::getSalary).thenComparing(Person::getAge)).map(Person::getName)
            .collect(Collectors.toList());
    // 先按工资再按年龄自定义排序(降序)
    List<string> newList4 = personList.stream().sorted((p1, p2) -> {
        if (p1.getSalary() == p2.getSalary()) {
            return p2.getAge() - p1.getAge();
        } else {
            return p2.getSalary() - p1.getSalary();
        }
    }).map(Person::getName).collect(Collectors.toList());
 
    System.out.println("按工资升序排序:" + newList);
    System.out.println("按工资降序排序:" + newList2);
    System.out.println("先按工资再按年龄升序排序:" + newList3);
    System.out.println("先按工资再按年龄自定义降序排序:" + newList4);}</string></string></string></string>

11、提取/组合

流也可以进行合并、去重、限制、跳过等操作。

private static void test05(){
    String[] arr1 = { "a", "b", "c", "d" };
    String[] arr2 = { "d", "e", "f", "g" };
    Stream<string> stream1 = Stream.of(arr1);
    Stream<string> stream2 = Stream.of(arr2);
    // concat:合并两个流 distinct:去重
    List<string> newList = Stream.concat(stream1, stream2).distinct().collect(Collectors.toList());
    // limit:限制从流中获得前n个数据
    List<integer> collect = Stream.iterate(1, x -> x + 2).limit(10).collect(Collectors.toList());
    // skip:跳过前n个数据
    List<integer> collect2 = Stream.iterate(1, x -> x + 2).skip(1).limit(5).collect(Collectors.toList());
 
    System.out.println("流合并:" + newList);
    System.out.println("limit:" + collect);
    System.out.println("skip:" + collect2);}</integer></integer></string></string></string>

12、读取文件的流操作

Résumé de lutilisation détaillée de Stream en Java8

13、计算两个list中的差集

//计算两个list中的差集
List<string> reduce1 = allList.stream().filter(item -> !wList.contains(item)).collect(Collectors.toList());</string>

推荐学习:《java视频教程

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer