MyTetra Share
Делитесь знаниями!
groupingBy
Время создания: 14.11.2020 18:16
Раздел: INFO - Development - JAVA - Collection - Stream
Запись: wwwlir/Tetra/master/base/1605348975btue9a2pzy/text.html на raw.githubusercontent.com

  • J ava
  • F ront-End
  • L inux
  • К онтакты
  • С амоучители

J ava Java 8  

Java 8 Stream reduce

Сентябрь 2, 2017 Vertex Academy filter ,Java ,java 8 stream reduce ,Java8 ,mapreduce ,method reference ,reduce ,Stream ,stream reduce

Данная статья написана командой Vertex Academy . Это одна из статей из нашего Учебника по Java 8. Надеемся, что данная статья Вам будет полезна. Приятного прочтения!


В этой статье мы рассмотрим сбор данных с помощью Stream-ов в Java.

1. Введение

Stream API  - новый способ взаимодействия с данными, представляя их в виде конечного потока данных.

С помощью Stream API в Java 8 стало возможно использование стратегии mapReduce

С ней мы сегодня и научимся работать.

2. Sum reduce

Посчитаем сумму чисел в списке


Java

public static void main(String[] args) { List<Integer> numbers = Arrays.asList(1, 2, 3, 5); Optional<Integer> sum = numbers.stream() .reduce((left, right) -> left + right); sum.ifPresent(System.out::println); //output 11 }


1

2

3

4

5

6

7

8

public static void main(String[] args) {

    List<Integer> numbers = Arrays.asList(1, 2, 3, 5);

 

    Optional<Integer> sum = numbers.stream()

            .reduce((left, right) -> left + right);

 

    sum.ifPresent(System.out::println); //output 11

}

Метод reduce принимает  лямбда-выражение  известное как аккумулятор (Accumulator), которое служит для сворачивания данных в одну "кучу".

А тепер посчитаем сумму начиная с 10


Java

public static void main(String[] args) { List<Integer> numbers = Arrays.asList(1, 2, 3, 5); Integer sum = numbers.stream() .reduce(10, (left, right) -> left + right); System.out.println(sum); //output 11 }


1

2

3

4

5

6

7

8

public static void main(String[] args) {

    List<Integer> numbers = Arrays.asList(1, 2, 3, 5);

 

    Integer sum = numbers.stream()

            .reduce(10, (left, right) -> left + right);

 

    System.out.println(sum); //output 11

}

Перегруженный метод reduce принимает начальное значение (identity) и аккумулятор.

В первом случае результат метода reduce вернул Optional<Integer> т.к. мы не указывали начальное значение.

Во втором случае мы указали начальное значение, и метод reduce уже возвращает обычный Integer.

Попоробуем более сложное выражение


Java

public static void main(String[] args) { List<Integer> numbers = Arrays.asList(1, 2, 3); // 1*10 + 2*10 + 3*10 Integer sum = numbers.stream() .reduce(10, (identity, val) -> identity * val, (left, right) -> left + right); System.out.println(sum); //output 60 }


1

2

3

4

5

6

7

8

9

public static void main(String[] args) {

    List<Integer> numbers = Arrays.asList(1, 2, 3);

 

    // 1*10 + 2*10 + 3*10

    Integer sum = numbers.stream()

            .reduce(10, (identity, val) -> identity * val, (left, right) -> left + right);

 

    System.out.println(sum); //output 60

}

В данном случае метод reduce принимает три параметра - identity, accumulator, combiner. Где accumulator умножает каждое значение из Stream-a на начальное значение (identity) а combiner собирает результат работы accumulator.

Выходит что наш Stream преобразовывается из 1, 2, 3 в 10, 20, 30 а послее просто суммируется.

3. Search reduce

3.1 Search min value

С помощью map reduce можно так же производить поиск

Найдем наименьшее число в массиве


Java

public static void main(String[] args) { List<Integer> numbers = Arrays.asList(1, 2, 3, 5, 7); Integer min = numbers.stream() .reduce(Integer.MAX_VALUE, (left, right) -> left < right ? left : right); System.out.println(min); //output 1 }


1

2

3

4

5

6

7

8

public static void main(String[] args) {

    List<Integer> numbers = Arrays.asList(1, 2, 3, 5, 7);

    

    Integer min = numbers.stream()

            .reduce(Integer.MAX_VALUE, (left, right) -> left < right ? left : right);

 

    System.out.println(min); //output 1

}

В данном примере мы указали начальное значение и аккумулятор который и оставляет меньшее значение.

Так же пример можно улучшить с помощью ссылки на метод  min в Integer


Java

public static void main(String[] args) { List<Integer> numbers = Arrays.asList(1, 2, 3, 5, 7); Integer min = numbers.stream() .reduce(Integer.MAX_VALUE, Integer::min); System.out.println(min); //output }


1

2

3

4

5

6

7

8

public static void main(String[] args) {

    List<Integer> numbers = Arrays.asList(1, 2, 3, 5, 7);

 

    Integer min = numbers.stream()

            .reduce(Integer.MAX_VALUE, Integer::min);

 

    System.out.println(min); //output

}

3.2 Search longest string

Попробуем найти самую длинную строку


Java

public static void main(String[] args) { List<String> strings = Arrays.asList("aaa", "bbb", "ccc", "ddd", "ffff"); String s = strings.stream() .reduce("", (left, right) -> left.length() > right.length() ? left : right); System.out.println(s); //output ffff }


1

2

3

4

5

6

7

8

public static void main(String[] args) {

    List<String> strings = Arrays.asList("aaa", "bbb", "ccc", "ddd", "ffff");

 

    String s = strings.stream()

            .reduce("", (left, right) -> left.length() > right.length() ? left : right);

 

    System.out.println(s); //output ffff

}

3.3 Complex search

Создадим класс Connection

class Connection { private String from; private String to; // constructors, getters }


1

2

3

4

5

class Connection {

    private String from;

    private String to;

// constructors, getters

}

а так же список всех связей, создав таким образом сеть


Java

List<Connection> network = Arrays.asList(new Connection("A", "B"), new Connection("A", "C"), new Connection("A", "D"), new Connection("B", "C") );


1

2

3

4

5

List<Connection> network = Arrays.asList(new Connection("A", "B"),

        new Connection("A", "C"),

        new Connection("A", "D"),

        new Connection("B", "C")

);

А теперь попробуем найти все связи, которые знает узел "A" с помощью mapReduce + filter

Для этого нам понадобится создать наш identity


Java

List<String> identity = new ArrayList<>();


1

List<String> identity = new ArrayList<>();

а так же accumulator


Java

BiFunction<List<String>, Connection, List<String>> accumulator = (strings, connection) -> { strings.add(connection.getTo()); return strings; };


1

2

3

4

BiFunction<List<String>, Connection, List<String>> accumulator = (strings, connection) -> {

    strings.add(connection.getTo());

    return strings;

};

где мы просто добавляем наши входящие узлы в список (identity) и возвращаем его.

И combiner


Java

BinaryOperator<List<String>> combiner = (strings, strings2) -> { strings.addAll(strings2); return strings; };


1

2

3

4

BinaryOperator<List<String>> combiner = (strings, strings2) -> {

    strings.addAll(strings2);

    return strings;

};

который соединяет два списка узлов в один.

А теперь используем все компоненты


Java

List<String> list = network.stream() .filter(p -> "A".equals(p.getFrom())) .reduce(identity, accumulator, combiner); System.out.println(list); //output [B, C, D]


1

2

3

4

5

List<String> list = network.stream()

        .filter(p -> "A".equals(p.getFrom()))

        .reduce(identity, accumulator, combiner);

 

System.out.println(list); //output [B, C, D]

Таким образом мы получили список узлов, которые знает узел "А"

Полный код примера


Java

public static void main(String[] args) { List<Connection> network = Arrays.asList(new Connection("A", "B"), new Connection("A", "C"), new Connection("A", "D"), new Connection("B", "C") ); List<String> identity = new ArrayList<>(); BiFunction<List<String>, Connection, List<String>> accumulator = (strings, connection) -> { strings.add(connection.getTo()); return strings; }; BinaryOperator<List<String>> combiner = (strings, strings2) -> { strings.addAll(strings2); return strings; }; List<String> list = network.stream() .filter(p -> "A".equals(p.getFrom())) .reduce(identity, accumulator, combiner); System.out.println(list); //output [B, C, D] }


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

public static void main(String[] args) {

    List<Connection> network = Arrays.asList(new Connection("A", "B"),

            new Connection("A", "C"),

            new Connection("A", "D"),

            new Connection("B", "C")

    );

 

    List<String> identity = new ArrayList<>();

 

    BiFunction<List<String>, Connection, List<String>> accumulator = (strings, connection) -> {

        strings.add(connection.getTo());

        return strings;

    };

 

    BinaryOperator<List<String>> combiner = (strings, strings2) -> {

        strings.addAll(strings2);

        return strings;

    };

 

    List<String> list = network.stream()

            .filter(p -> "A".equals(p.getFrom()))

            .reduce(identity, accumulator, combiner);

 

    System.out.println(list); //output [B, C, D]

}

 
MyTetra Share v.0.59
Яндекс индекс цитирования