Может кто-нибудь распаковать эту очень краткую функцию Java в более подробный пример? - PullRequest
0 голосов
/ 14 марта 2020

Я пытаюсь портировать этот Java учебник на Xojo. Я изо всех сил пытаюсь распаковать нижеприведенную функцию Set, потому что, будучи коротким и элегантным, она превращает множество преобразований в небольшое пространство, и я не уверен, правильно ли я ее понимаю. Это сложно, так как Java не является моим основным языком, а Xojo не поддерживает обобщенные формы:

public interface GraphNode {
    String getId();
}


public class Graph<T extends GraphNode> {
    private final Set<T> nodes;
    private final Map<String, Set<String>> connections;

    public T getNode(String id) {
        return nodes.stream()
            .filter(node -> node.getId().equals(id))
            .findFirst()
            .orElseThrow(() -> new IllegalArgumentException("No node found with ID"));
    }

    public Set<T> getConnections(T node) {
        return connections.get(node.getId()).stream()
            .map(this::getNode)
            .collect(Collectors.toSet());
    }
}

Я могу понять, что происходит до вызова метода .stream():

  1. Получить Id переданного node GraphNode
  2. Получить Set<String> от connections Map, ключ которого соответствует найденному Id

Я не понимаю, что здесь происходит:

.map(this::getNode).collect(Collectors.toSet())

Может ли кто-нибудь предоставить псевдокод, чтобы объяснить это?

Ответы [ 2 ]

3 голосов
/ 14 марта 2020

это означает map id в Node и положить (собрать) его в set

this::getNode переводится в: из этого класса используйте getNode на id который является просто syntacti c сахар для .map(id -> getNode(id)).collect(Collectors.toSet())

public T getNode(String id) {
        return nodes.stream()
            .filter(node -> node.getId().equals(id))
            .findFirst()
            .orElseThrow(() -> new IllegalArgumentException("No node found with ID"));
    }

Этот код возвращает первый узел с id в узлах Set, nodes.stream() .filter(node -> node.getId().equals(id)) вернет набор, где каждый узел имеет id переданный в качестве аргумента, findFirst() вернет первый узел в наборе

public Set<T> getConnections(T node) {
        return connections.get(node.getId()).stream()
            .map(this::getNode)
            .collect(Collectors.toSet());
    }

, поскольку connections является картой, connections.get(node.getId()) вернет значение с ключом node.getId(), затем map(this::getNode) отображает его с id на Node с использованием getNode(String id) и, наконец, помещает его в set

1 голос
/ 14 марта 2020

Потоки в основном прославляются для каждого цикла. Обычно, когда вы видите XXX.stream() или метод, который возвращает Stream<XXX>, это означает «для каждой вещи в XXX» и «Для каждого XXX ...» соответственно.

Итак, вот оно говорит "для каждой строки в Set<String> ..."

map означает "превратить каждую вещь во что-то другое", другими словами, преобразование . С a для l oop, это похоже на псевдокод:

For Each x In set
    f(x)
Next x

f - это функция, которую вы передаете. В данном случае это getNode.

Теперь , getNode возвращает T, поэтому каждый элемент в нашем исходном наборе был преобразован в T. Последний вызов - collect, что означает помещение всех этих элементов обратно в некоторую коллекцию или какой-либо другой объект. В этом случае мы помещаем все эти преобразованные T обратно в новый Set.

Весь код в псевдокоде будет:

originalSet = connections.get(node.getId())
newSet = []
For Each x In originalSet
    newSet.add(x)
Next x
...