Глубокое понимание операций с потоками Java Stream сделает ваш код еще мощнее!

Java
Глубокое понимание операций с потоками Java Stream сделает ваш код еще мощнее!

«Эта статья участвовала в мероприятии Haowen Convocation Order, щелкните, чтобы просмотреть:Двойные заявки на внутреннюю и внешнюю стороны, призовой фонд в 20 000 юаней ждет вас, чтобы бросить вызов!"

концепция

StreamНабор элементов, подлежащих обработке, рассматривается как некий поток, в процессе потока с помощьюStream APIВыполнять операции над элементами в потоке, такие как фильтрация, сортировка, агрегирование и т. д.

image-20210701194245361

StreamВ основном есть два типа операторов:中间操作符и终止操作符

Промежуточный оператор

Для потока данных после того, как промежуточный оператор выполнит указанный обработчик, поток данных все еще может быть передан оператору следующего уровня.

Есть 8 промежуточных операторов (параллельный и последовательный исключаются, эти две операции не предполагают операций по обработке потоков данных):

  1. map(mapToInt, mapToLong, mapToDouble) оператор преобразования, такой как A->B, здесь по умолчанию предоставляется оператор в int, long, double.
  2. flatmap(flatmapToInt, flatmapToLong, flatmapToDouble) Операция Flatmap, такая как сведение int[]{2,3,4} в 2, 3, 4, то есть из исходных данных в 3 данных, что предоставляется по умолчанию здесь Оператор, который сглаживается в int, long и double.
  3. ограничить операцию ограничения тока, например, если есть 10 потоков данных, я могу использовать только первые 3.
  4. Удаленная операция дедупликации, дедупликация повторяющихся элементов, использует метод equals внизу.
  5. filter Работа фильтра, фильтрация нежелательных данных.
  6. peek выбирает операции, если вы хотите выполнить некоторые операции с данными, такие как: чтение, редактирование, изменение и т. д.
  7. пропустить операцию пропуска, пропустить определенные элементы.
  8. sorted(unordered) Операция сортировки, сортировка элементов, при условии, что реализован интерфейс Comparable, конечно же можно настроить и компаратор.

оператор завершения

После того, как данные прошли промежуточные операции обработки, наступает очередь оператора терминации;

Оператор завершения используется для сбора или потребления данных. Данные не будут передаваться при достижении операции завершения. Оператор завершения можно использовать только один раз.

  1. Операция сбора коллекции состоит в том, чтобы собрать все данные.Эта операция очень важна.Официально предоставленные коллекторы предоставляют много сборщиков.Можно сказать, что ядро ​​Stream лежит в коллекторах.
  2. count Статистическая операция, подсчет конечного количества данных.
  3. findFirst, findAny Операции поиска, найти первый, найти любой возвращаемый тип не является обязательным.
  4. noneMatch, allMatch, anyMatch операция сопоставления, наличие элемента, удовлетворяющего условиям в потоке данных. Возвращаемое значение является логическим значением.
  5. Операция минимального, максимального максимального значения требует, чтобы пользовательский компаратор возвращал максимальное и минимальное значения в потоке данных.
  6. Операция сокращения уменьшает значение всего потока данных до значения.Нижний слой count, min и max использует сокращение.
  7. forEach, forEachOrdered операции обхода, вот расход конечных данных.
  8. Операция массива toArray преобразует элементы потока данных в массив.

Создание потока

1. Пройтиjava.util.Collection.stream()метод создает поток из коллекции

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

2. Используйтеjava.util.Arrays.stream(T[] array)метод создает поток из массива

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

3. ИспользуйтеStreamстатический метод: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); // 0 3 6 9

Stream<Double> stream3 = Stream.generate(Math::random).limit(3);
stream3.forEach(System.out::println);

Выходной результат:

3
6
9
0.8106623442686114
0.11554643727388458
0.1404645961428974

Process finished with exit code 0

streamиparallelStreamПростое различие:

streamявляется последовательным потоком, и основной поток последовательно выполняет операции над потоком;parallelStreamЭто параллельный поток, который работает с потоком в режиме многопоточного параллельного выполнения, но только в том случае, если обработка данных в потоке не имеет последовательных требований.

Например, чтобы отфильтровать нечетные числа в коллекции, разница в обработке между ними составляет:

image-20210701230623951

Использование потока

Обход/сопоставление (foreach/find/match)

StreamОн также поддерживает сходный с коллекцией обход и сопоставление элементов, ноStreamЭлементы вOptionalтип есть.StreamОбход и сопоставление очень просты.

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 < 6);
        System.out.println("匹配第一个值:" + findFirst.get());
        System.out.println("匹配任意一个值:" + findAny.get());
        System.out.println("是否存在大于6的值:" + anyMatch);
        
    }
}

Выходной результат:

7
9
8
匹配第一个值:7
匹配任意一个值:8
是否存在大于6的值:true

Process finished with exit code 0

фильтр

Фильтрация — это операция проверки элементов в потоке в соответствии с определенными правилами и извлечения подходящих элементов в новый поток.

ОтфильтрованоIntegerЭлементов в наборе больше 7, и выведите их

public class StreamTest {

    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(6, 7, 3, 8, 1, 2, 9);
        Stream<Integer> stream = list.stream();
        stream.filter(x -> x > 7).forEach(System.out::println);
    }
}

Выходной результат:

8
9

Process finished with exit code 0

Агрегация (макс./мин./количество)

max,min,countВы должны быть знакомы с этими словами, да, мы часто используем их для статистики данных в mysql. Эти концепции и способы использования также представлены в потоке Java, что значительно облегчает нашу статистическую работу с коллекциями и массивами.

Случай 1: получитьStringСамый длинный элемент в коллекции.

public class StreamTest {

    public static void main(String[] args) {
        List<String> list = Arrays.asList("adnm", "admmt", "pot", "xbangd", "weoujgsd");
        Optional<String> max = list.stream().max(Comparator.comparing(String::length));
        System.out.println("最长的字符串:" + max.get());
    }
}

Выходной результат:

最长的字符串:weoujgsd

Process finished with exit code 0

Случай 2: получитьIntegerМаксимальное значение в коллекции.

public class StreamTest {

    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(7, 6, 9, 4, 11, 6);
        // 自然排序
        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("自然排序的最大值:" + max.get());
        System.out.println("自定义排序的最大值:" + max2.get());
    }
}

Выходной результат:

自然排序的最大值:11
自定义排序的最大值:11

Process finished with exit code 0

Случай 3: вычисленияIntegerКоличество элементов в наборе больше 6.

public class StreamTest {

    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(7, 6, 4, 8, 2, 11, 9);
        long count = list.stream().filter(x -> x > 6).count();
        System.out.println("list中大于6的元素个数:" + count);
    }
}

Выходной результат:

list中大于6的元素个数:4

Process finished with exit code 0

карта (карта/плоская карта)

Отображение, которое может отображать элементы одного потока в другой поток в соответствии с определенными правилами отображения. разделен наmapиflatMap:

  • map: получает функцию в качестве параметра, функция будет применена к каждому элементу и сопоставлена ​​с новым элементом.
  • flatMap: принимает функцию в качестве параметра, заменяет каждое значение в потоке другим потоком и объединяет все потоки в один поток.

Случай 1: Все элементы массива английских строк изменены на верхний регистр. +3 за каждый элемент целочисленного массива.

public class StreamTest {

    public static void main(String[] args) {
        String[] strArr = { "abcd", "bcdd", "defde", "fTr" };
        List<String> strList = Arrays.stream(strArr).map(String::toUpperCase).collect(Collectors.toList());
        System.out.println("每个元素大写:" + strList);
        List<Integer> intList = Arrays.asList(1, 3, 5, 7, 9, 11);
        List<Integer> intListNew = intList.stream().map(x -> x + 3).collect(Collectors.toList());
        System.out.println("每个元素+3:" + intListNew);
    }
}

Выходной результат:

每个元素大写:[ABCD, BCDD, DEFDE, FTR]
每个元素+3:[4, 6, 8, 10, 12, 14]

Process finished with exit code 0

Случай 2: объединить два массива символов в новый массив символов.

public class StreamTest {

    public static void main(String[] args) {
        List<String> list = Arrays.asList("m,k,l,a", "1,3,5,7");
        List<String> listNew = list.stream().flatMap(s -> {
            // 将每个元素转换成一个stream
            String[] split = s.split(",");
            Stream<String> s2 = Arrays.stream(split);
            return s2;
        }).collect(Collectors.toList());
        System.out.println("处理前的集合:" + list);
        System.out.println("处理后的集合:" + listNew);
    }
}

Выходной результат:

处理前的集合:[m,k,l,a, 1,3,5,7]
处理后的集合:[m, k, l, a, 1, 3, 5, 7]

Process finished with exit code 0

уменьшать

Сокращение, также известное как сокращение, как следует из названия, заключается в уменьшении потока до значения, которое может реализовать операцию суммирования, умножения и максимизации набора.

Случай 1: спроситеIntegerСумма, произведение и максимальное значение элементов коллекции.

public class StreamTest {

    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 3, 2, 8, 11, 4);
        // 求和方式1
        Optional<Integer> sum = list.stream().reduce(Integer::sum);
        // 求和方式2
        Optional<Integer> sum2 = list.stream().reduce(Integer::sum);
        // 求和方式3
        Integer sum3 = list.stream().reduce(0, Integer::sum);
        // 求乘积
        Optional<Integer> product = list.stream().reduce((x, y) -> x * y);
        // 求最大值方式1
        Optional<Integer> max = list.stream().reduce((x, y) -> x > y ? x : y);
        // 求最大值写法2
        Integer max2 = list.stream().reduce(1, Integer::max);
        System.out.println("list求和:" + sum.get() + "," + sum2.get() + "," + sum3);
        System.out.println("list求积:" + product.get());
        System.out.println("list求和:" + max.get() + "," + max2);
    }
}

Выходной результат:

list求和:29,29,29
list求积:2112
list求和:11,11

Process finished with exit code 0

Коллекция (toList/toSet/toMap)

Поскольку поток не хранит данные, после обработки данных в потоке данные в потоке необходимо повторно собрать в новую коллекцию.toList,toSetиtoMapчаще используется, и естьtoCollection,toConcurrentMapи более сложное использование.

Ниже приведен пример демонстрацииtoList,toSetиtoMap:

public class Person {

    private String name;  // 姓名
    private int salary; // 薪资
    private int age; // 年龄
    private String sex; //性别
    private String area;  // 地区

    // 构造方法
    public Person(String name, int salary, int age,String sex,String area) {
        this.name = name;
        this.salary = salary;
        this.age = age;
        this.sex = sex;
        this.area = area;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getSalary() {
        return salary;
    }

    public void setSalary(int salary) {
        this.salary = salary;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getArea() {
        return area;
    }

    public void setArea(String area) {
        this.area = area;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", salary=" + salary +
                ", age=" + age +
                ", sex='" + sex + '\'' +
                ", area='" + area + '\'' +
                '}';
    }
}
public class StreamTest {

    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 6, 3, 4, 6, 7, 9, 6, 20);
        List<Integer> listNew = list.stream().filter(x -> x % 2 == 0).collect(Collectors.toList());
        Set<Integer> set = list.stream().filter(x -> x % 2 == 0).collect(Collectors.toSet());
        List<Person> personList = new ArrayList<Person>();
        personList.add(new Person("Tom", 8900, 23, "male", "New York"));
        personList.add(new Person("Jack", 7000, 25, "male", "Washington"));
        personList.add(new Person("Lily", 7800, 21, "female", "Washington"));
        personList.add(new Person("Anni", 8200, 24, "female", "New York"));
        Map<?, Person> map = personList.stream().filter(p -> p.getSalary() > 8000)
                .collect(Collectors.toMap(Person::getName, p -> p));
        System.out.println("toList:" + listNew);
        System.out.println("toSet:" + set);
        System.out.println("toMap:" + map);
    }
}

Выходной результат:

toList:[6, 4, 6, 6, 20]
toSet:[4, 20, 6]
toMap:{Tom=Person{name='Tom', salary=8900, age=23, sex='male', area='New York'}, Anni=Person{name='Anni', salary=8200, age=24, sex='female', area='New York'}}

Process finished with exit code 0

Статистика (счет/усреднение)

CollectorsПредоставляется ряд статических методов для статистики:

  • считать:count
  • Средняя стоимость:averagingInt,averagingLong,averagingDouble
  • Лучшее значение:maxBy,minBy
  • Итог:summingInt,summingLong,summingDouble
  • Статистика по всему вышеперечисленному:summarizingInt,summarizingLong,summarizingDouble

Случай: Статистика по количеству сотрудников, средней заработной плате, общей заработной плате и максимальной заработной плате.

public class StreamTest {

    public static void main(String[] args) {
        List<Person> personList = new ArrayList<Person>();
        personList.add(new Person("Tom", 8900, 23, "male", "New York"));
        personList.add(new Person("Jack", 7000, 25, "male", "Washington"));
        personList.add(new Person("Lily", 7800, 21, "female", "Washington"));
        // 求总数
        long count = personList.size();
        // 求平均工资
        Double average = personList.stream().collect(Collectors.averagingDouble(Person::getSalary));
        // 求最高工资
        Optional<Integer> max = personList.stream().map(Person::getSalary).max(Integer::compare);
        // 求工资之和
        int sum = personList.stream().mapToInt(Person::getSalary).sum();
        // 一次性统计所有信息
        DoubleSummaryStatistics collect = personList.stream().collect(Collectors.summarizingDouble(Person::getSalary));
        System.out.println("员工总数:" + count);
        System.out.println("员工平均工资:" + average);
        System.out.println("员工最高工资:" + max.get());
        System.out.println("员工工资总和:" + sum);
        System.out.println("员工工资所有统计:" + collect);
    }
}

Выходной результат:

员工总数:3
员工平均工资:7900.0
员工最高工资:8900
员工工资总和:23700
员工工资所有统计:DoubleSummaryStatistics{count=3, sum=23700.000000, min=7000.000000, average=7900.000000, max=8900.000000}

Process finished with exit code 0

Группировка (partitioningBy/groupingBy)

  • Раздел: будетstreamДелится на две по условиюMap, например, сотрудники делятся на две части в зависимости от того, превышает ли их зарплата 8000.
  • Группировка: разделите коллекцию на несколько карт, например, сгруппируйте сотрудников по полу. Различают одноуровневую группировку и многоуровневую группировку.

Кейс: Разделите сотрудников на две части в зависимости от того, превышает ли их зарплата 8000; сгруппируйте сотрудников по полу и региону.

public class StreamTest {

    public static void main(String[] args) {
        List<Person> personList = new ArrayList<Person>();
        personList.add(new Person("Tom", 8900, 23, "male", "Washington"));
        personList.add(new Person("Jack", 7000, 25, "male", "Washington"));
        personList.add(new Person("Lily", 7800, 21, "female", "New York"));
        personList.add(new Person("Anni", 8200, 24, "female", "New York"));
        // 将员工按薪资是否高于8000分组
        Map<Boolean, List<Person>> part = personList.stream().collect(Collectors.partitioningBy(x -> x.getSalary() > 8000));
        // 将员工按性别分组
        Map<String, List<Person>> group = personList.stream().collect(Collectors.groupingBy(Person::getSex));
        // 将员工先按性别分组,再按地区分组
        Map<String, Map<String, List<Person>>> 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);
    }
}

Выходной результат:

员工按薪资是否大于8000分组情况:{false=[Person{name='Jack', salary=7000, age=25, sex='male', area='Washington'}, Person{name='Lily', salary=7800, age=21, sex='female', area='New York'}], true=[Person{name='Tom', salary=8900, age=23, sex='male', area='Washington'}, Person{name='Anni', salary=8200, age=24, sex='female', area='New York'}]}
员工按性别分组情况:{female=[Person{name='Lily', salary=7800, age=21, sex='female', area='New York'}, Person{name='Anni', salary=8200, age=24, sex='female', area='New York'}], male=[Person{name='Tom', salary=8900, age=23, sex='male', area='Washington'}, Person{name='Jack', salary=7000, age=25, sex='male', area='Washington'}]}
员工按性别、地区:{female={New York=[Person{name='Lily', salary=7800, age=21, sex='female', area='New York'}, Person{name='Anni', salary=8200, age=24, sex='female', area='New York'}]}, male={Washington=[Person{name='Tom', salary=8900, age=23, sex='male', area='Washington'}, Person{name='Jack', salary=7000, age=25, sex='male', area='Washington'}]}}

Process finished with exit code 0

присоединение

joiningЭлементы в потоке могут быть объединены в строку с помощью специального конкатенатора (или прямого объединения, если его нет).

public class StreamTest {

    public static void main(String[] args) {
        List<Person> personList = new ArrayList<Person>();
        personList.add(new Person("Tom", 8900, 23, "male", "New York"));
        personList.add(new Person("Jack", 7000, 25, "male", "Washington"));
        personList.add(new Person("Lily", 7800, 21, "female", "Washington"));
        String names = personList.stream().map(Person::getName).collect(Collectors.joining(","));
        System.out.println("所有员工的姓名:" + names);
        List<String> list = Arrays.asList("A", "B", "C");
        String string = list.stream().collect(Collectors.joining("-"));
        System.out.println("拼接后的字符串:" + string);
    }
}

Выходной результат:

所有员工的姓名:Tom,Jack,Lily
拼接后的字符串:A-B-C

Process finished with exit code 0

отсортированный

sorted, промежуточная операция. Есть два вида:

  • sorted(): Естественная сортировка, элементы в потоке должны быть реализованыComparableинтерфейс
  • sorted(Comparator com):ComparatorСортировщик пользовательской сортировки

Кейс: Отсортируйте сотрудников по зарплате от высокой к низкой (та же зарплата будет отсортирована по возрасту от старшего к младшему)

public class StreamTest {

    public static void main(String[] args) {
        List<Person> personList = new ArrayList<Person>();
        personList.add(new Person("Sherry", 9000, 24, "female", "New York"));
        personList.add(new Person("Tom", 8900, 22, "male", "Washington"));
        personList.add(new Person("Jack", 9000, 25, "male", "Washington"));
        personList.add(new Person("Lily", 8800, 26, "male", "New York"));
        personList.add(new Person("Alisa", 9000, 26, "female", "New York"));
        // 按工资升序排序(自然排序)
        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);
    }
}

Выходной результат:

按工资升序排序:[Lily, Tom, Sherry, Jack, Alisa]
按工资降序排序:[Sherry, Jack, Alisa, Tom, Lily]
先按工资再按年龄升序排序:[Lily, Tom, Sherry, Jack, Alisa]
先按工资再按年龄自定义降序排序:[Alisa, Jack, Sherry, Tom, Lily]

Process finished with exit code 0

извлечь/объединить

Потоки также можно объединять, дедуплицировать, ограничивать, пропускать и т. д.

public class StreamTest {

    public static void main(String[] args) {
        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);
    }
}

Выходной результат:

流合并:[a, b, c, d, e, f, g]
limit:[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
skip:[3, 5, 7, 9, 11]

Process finished with exit code 0

пейджинговая операция

Возможности потокового API заключаются не только в выполнении различных комбинированных операций над коллекциями, но и в поддержке операций пейджинга.

Например, отсортируйте следующие массивы от меньшего к большему.После завершения сортировки начните с первой строки и запросите 10 фрагментов данных.Операция выглядит следующим образом:

//需要查询的数据
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5, 10, 6, 20, 30, 40, 50, 60, 100);
List<Integer> dataList = numbers.stream().sorted(Integer::compareTo).skip(0).limit(10).collect(Collectors.toList());
System.out.println(dataList.toString());

Выходной результат:

[2, 2, 3, 3, 3, 5, 6, 7, 10, 20]

Process finished with exit code 0

Параллельная работа

Так называемый параллелизм означает, что несколько задач выполняются в один и тот же момент времени и обрабатываются разными процессорами без вытеснения ресурсов друг у друга, в то время как параллелизм означает, что несколько задач выполняются одновременно в один и тот же момент времени, но обрабатываются одним и тем же процессором. ЦП обрабатывает и вытесняет ресурсы друг у друга.

Между параллельной операцией и последовательной операцией потокового API есть только одно отличие, а остальные одинаковые.Например, мы используем parallelStream ниже для вывода количества пустых строк:

List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd", "", "jkl");
// 采用并行计算方法,获取空字符串的数量
long count = strings.parallelStream().filter(String::isEmpty).count();
System.out.println(count);

В реальном использовании,并行操作не обязательно串行操作быстрый! Для простых операций их количество очень велико, а если сервер многоядерный, то рекомендуется использовать параллелизм Stream! И наоборот, использование последовательной операции более надежно!

Коллекция для операции сопоставления

В реальном процессе разработки одной из наиболее часто используемых операций является использование поля первичного ключа в элементе коллекции в качестве ключа и элемента в качестве значения для реализации требования преобразования коллекции в карту Это требование очень полезно в сборке данных много.

public static void main(String[] args) {
    List<Person> personList = new ArrayList<>();
    personList.add(new Person("Tom",7000,25,"male","安徽"));
    personList.add(new Person("Jack",8000,30,"female","北京"));
    personList.add(new Person("Lucy",9000,40,"male","上海"));
    personList.add(new Person("Airs",10000,40,"female","深圳"));
    Map<Integer, Person> collect = personList.stream().collect(Collectors.toMap(Person::getAge, v -> v, (k1, k2) -> k1));
    System.out.println(collect);
}

Выходной результат:

{40=Person{name='Lucy', salary=9000, age=40, sex='male', area='上海'}, 25=Person{name='Tom', salary=7000, age=25, sex='male', area='安徽'}, 30=Person{name='Jack', salary=8000, age=30, sex='female', area='北京'}}

Process finished with exit code 0

ОткрытымCollectors.toMapИсходный код метода, давайте посмотрим.

public static <T, K, U>
    Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
                                    Function<? super T, ? extends U> valueMapper,
                                    BinaryOperator<U> mergeFunction) {
    return toMap(keyMapper, valueMapper, mergeFunction, HashMap::new);
}

Из таблицы параметров видно, что:

  • Первый параметр: указывает ключ
  • Второй параметр: указывает значение
  • Третий параметр: указывает на определенное правило

вышесказанноеCollectors.toMap(Person::getAge, v -> v, (k1,k2) -> k1), что означает, чтоageсодержание какkey,v -> vдолжен представлять элементpersonв видеvalue(k1,k2) -> k1означает, что если есть то же самоеkey, возьмите первый совпадающий элемент в качестве содержимого и отбросьте второй!

конец

Эта статья в основном посвящена работе jdk stream API в сочетании с фактическими ежедневными потребностями разработки, делает краткий обзор и делится. Я надеюсь, что вы сможете следовать дальше, чтобы углубить свое впечатление, и я верю, что вы сможете освоить начальное использование этих операторов; в последующих статьях я буду шаг за шагом углублять вас в Stream. После прочтения, надеюсь, вы поставите лайк, ха-ха.