У меня проблемы с потоками. По сути, у меня есть Map<Integer, Bucket>
, а у каждого ведра есть Set<Node>
. Что я хочу сделать, так это вернуть List<Node>
, содержащий все узлы во всех сегментах. На данный момент я просматриваю все ведра с помощью цикла for и для каждого ведра добавляю все узлы в список, как показано ниже.
public static synchronized List<Node> getNodes() {
List<Node> nodes = new ArrayList<>();
Collection<Bucket> bucketCollection = buckets.values();
for (Bucket b : bucketCollection) {
for (Node n : b.getNodes()) {
nodes.add(n);
}
}
return nodes;
}
Это работает и делает то, что должно делать. Однако у меня возникли проблемы с переписыванием этой функции с использованием потоков. Я пробовал следующий код, но он не работает, потому что возвращает List<Set<Node>>
вместо List<Node>
.
public static synchronized List<Node> getNodes() {
return buckets.values().stream()
.map(Bucket::getNodes)
.collect(Collectors.toList());
}
При этом после карты у меня есть Stream<Set<Node>>
, но мне нужно иметь Stream<Node>
, прежде чем звонить collect(Collectors.toList())
. Как я могу это сделать?
map
превращает одну «штучку» в другую «штучку». 1 вещь становится 1 вещью. Это не то, что вы хотите здесь; вы хотите, чтобы 1 вещь превратилась в 0 для многих вещей. Метод, который вы ищете для этого, — квартираКарта.
return buckets.values().stream()
.map(Bucket::getNodes)
.flatMap(Set::stream)
.collect(Collectors.toList())
;
в C# linq это
SelectMany
.