I have a Map<String , String> that points to links from A to B. I want to link all possible routes. eg:
[A , B] [B , C] [C , D] [E , F] [F , G] [H , I]
displays
[A , B , C , D] [E , F , G] [H , I]
I found a similar question here (but didnโt completely fulfill my requirement): https://stackoverflow.com/a/2128778
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 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 works correctly:
list = H -> I list = E -> F -> G list = A -> B -> C -> D
But I do not like my decision. Because I feel that this can be solved in a more functional style. Here I smell stream.fold() . I tried, but in vain, to convert my code into a pure functional style: this means that there is no creation of intermediate objects ...
Is it possible? Any hints are appreciated!