Ho un Map<String , String>
che indica i collegamenti da A a B. Voglio concatenare tutti i percorsi possibili. per esempio:java 8 stile funzionale dei collegamenti di concatenamento
[A , B]
[B , C]
[C , D]
[E , F]
[F , G]
[H , I]
uscita volontà
[A , B , C , D]
[E , F , G]
[H , I]
ho trovato domanda simile qui (ma non adempie pienamente la mia richiesta): https://stackoverflow.com/a/10176274/298430
E qui è la mia soluzione:
public static <T> Set<List<T>> chainLinks(Map<T , T> map) {
Set<List<T>> resultSet = new HashSet<>();
map.forEach((from, to) -> {
if (!map.containsValue(from)) {
List<T> list = new ArrayList<>();
list.add(from);
list.addAll(inner(to, map));
resultSet.add(list);
}
});
return resultSet;
}
private static <T> List<T> inner(T from , Map<T , T> map) {
if (map.containsKey(from)) {
List<T> list = new ArrayList<>();
list.add(from);
list.addAll(inner(map.get(from), map));
return list;
} else {
List<T> end = new ArrayList<>();
end.add(from);
return end;
}
}
e il test case:
@Test
public void testChainLinks() {
Map<String , String> map = new HashMap<String , String>() {{
put("A" , "B");
put("B" , "C");
put("C" , "D");
put("E" , "F");
put("F" , "G");
put("H" , "I");
}};
Utils.chainLinks(map).forEach(list -> {
logger.info("list = {}" , list.stream().collect(Collectors.joining(" -> ")));
});
}
funziona correttamente:
list = H -> I
list = E -> F -> G
list = A -> B -> C -> D
Ma non mi piace la mia soluzione. Perché sento che può essere risolto in uno stile più funzionale. Posso sentire l'odore di stream.fold()
qui. Ho provato, ma invano, a convertire il mio codice in uno stile puramente funzionale: il che significa nessuna creazione di oggetti intermedi ...
È possibile? Ogni suggerimento è riconoscente!
Siamo spiacenti, refuso. Intendo Stream.reduce(). – smallufo
Speriamo che i tuoi input non abbiano cicli come 'put (" A "," B "); put ("B", "A"); '. Altrimenti le soluzioni fornite non funzioneranno. –
Sì, sono sicuro che non ci saranno collegamenti ciclici. – smallufo