Применение изменений к другим объектам с использованием потоков - PullRequest
0 голосов
/ 29 марта 2019

Я изучаю API потоков Java 8, пробуя разные примеры.Я пытаюсь сформировать HashMap из ArrayList с помощью метода streams .map ().(Я знаю о методе .groupingBy, но я пытаюсь понять основную логику потоковых операций.) Когда я запускаю свой код без вызова метода forEach () (или любой терминальной операции), изменения не применяются к моему HashMap <> ион остается пустым.Но вызов терминальной операции позволяет защитить сделанные мной изменения.Я думал, что терминальные операции используются только для возврата не потоковых значений и конечных потоков.Кто-нибудь может объяснить, почему это происходит так?

class Main {

    public static void main(String[] args) {

    // Create a list of arrays then form a HasMap based on entries of list
    List<String[]> list3 = new ArrayList<String[]>();
    String[] entry1 = {"a","b","c"};
    String[] entry2 = {"d","e","f"};
    String[] entry3 = {"g","h","i"};
    list3.add(entry1);
    list3.add(entry2);
    list3.add(entry3);

    // hashmap
    HashMap<String, String[]> map1 = new HashMap<String, String[]>();

    // streamize the list to form hashmap
    list3.stream()
         .map(entry ->  {
                            String key = entry[0];
                            String[] value = {entry[1],entry[2]};
                            map1.put(key, value);
                            // must return a String[]
                            return entry;
                        })
         // CHANGES ARE ONLY APPLIED WHEN TERMINAL OPERATIONS CALLED ???
         .forEach(entry -> {});

    // print elements
    for (Map.Entry<String,String[]> entry : map1.entrySet()) {
        System.out.println(entry);
    }

}

// Без терминала op

                              //Empty

// С терминалом op

a = [Ljava.lang.String; @ 7921b0a2

d = [Ljava.lang.String; @ 174d20a

g = [Ljava.lang.String; @ 66d2e7d9

1 Ответ

0 голосов
/ 29 марта 2019

Я думаю, что хорошо отметить, что основная причина, по которой ваш HashMap не заполнен, заключается в том, что ваш код помещен в тело лямбда-выражения .Лямбда похожа на анонимный внутренний класс:

jbutton.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent event) {
        doSomething();
    }
});

Если вы определили что-то подобное, метод doSomething() выполняется не сразу, а метод addActionListener где-то сохраняет экземпляр ActionListenerкак переменная экземпляра, поэтому она может быть использована позже.Это означает, что вы фактически определяете только метод, но еще не вызываете его.

Метод map интерфейса Stream (какую бы реализацию вы не использовали) принимает экземпляр Function, который является только определением.Он только хранит этот Function где-то, но не выполняет тело вашего лямбда-выражения.

Stream Реализации ленивы.Они созданы для того, чтобы ничего не делать, пока они не должны.Это только тот случай, когда вызывающему на самом деле нужен некоторый результат (т. Е. Сбор).

Как только вы вызываете операцию терминала, , а затем реализация Stream фактически применяет всенеобходимые этапы преобразования и фильтрации и возвращают некоторую форму результата.

Связано:


Примечание: потоковые операции не должны иметь побочных эффектов.Это означает, что вы должны избегать таких вещей, как map1.put(key, value).

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