I have a Map<String , String>
which indicates links from A to B. I want to chain all possible routes. for example :
[A , B]
[B , C]
[C , D]
[E , F]
[F , G]
[H , I]
will output
[A , B , C , D]
[E , F , G]
[H , I]
I found similar question here (but not fully fulfills my requirement) : https://stackoverflow.com/a/10176274/298430
And here is my solution :
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;
}
}
and the 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(" -> ")));
});
}
It does work correctly :
list = H -> I
list = E -> F -> G
list = A -> B -> C -> D
But I don't like my solution. Because I feel it can be solved in a more functional-style . I can feel the smell of stream.fold()
here . I tried but in vain to convert my code to a pure functional style : which means no intermediate objects creation...
Is it possible ? Any hints are grateful !