How to recursive get absolute path from list of folder objects?

Viewed 121

There are list of folder objects, I need to concat them to absolute path. Each folder has field "parentId"(Nullable) and "orderNumber", like:

class Folder {
    folderId;
    desc;
    parentId;
    orderNumber;
}

So, if parentId == null -> folder is the first one in absolute path, if not -> we should get parent folder and so on.

I did it this way, maybe there is a simpler way?

public static void main(String[] args) {
        List<Folder> list = new ArrayList<Folder>();
        list.add(new Folder(1, null, "root1"));
        list.add(new Folder(3, 2, "child2"));
        list.add(new Folder(2, 1, "child1"));
        list.add(new Folder(5, 4, "child4"));
        list.add(new Folder(6, null, "root2"));
        list.add(new Folder(4, 3, "child3"));

        Integer fromId = 5;
        String path = getAbsolutePath(list, getFolderById(list, fromId));
        System.out.println(path);
    }

    public static String getAbsolutePath(List<Folder> list, Folder folder) {
        String path = "";
        Integer parentId = folder.getParentId();
        if (parentId != null) {
            Folder parent = getFolderById(list, parentId);
            path += getAbsolutePath(list, parent) + "/";
        }
        path += folder.getDesc();
        return path;
    }

    public static Folder getFolderById(List<Folder> list, Integer folderId) {
        return list.stream().filter(row -> row.getId() == folderId).findFirst().get();
    }

Output: root1/child1/child2/child3/child4

updated:

public static void main(String[] args) {
        List<Folder> list = new ArrayList<Folder>();
        list.add(new Folder(1, null, "root1"));
        list.add(new Folder(3, 2, "child2"));
        list.add(new Folder(2, 1, "child1"));
        list.add(new Folder(5, 4, "child4"));
        list.add(new Folder(6, null, "root2"));
        list.add(new Folder(4, 3, "child3"));
        Map<Integer, Folder> folderMap = list.stream().collect(Collectors.toMap(
                Folder::getId, folder -> folder
        ));

        Integer fromId = 5;
        String path = getAbsolutePath(folderMap, folderMap.get(fromId));
        System.out.println(path);
    }

    public static String getAbsolutePath(Map<Integer, Folder> folderMap, Folder folder) {
        Folder current = folder;
        List<String> buffer = new ArrayList<>();
        while(true) {
            Integer parentId = current.getParentId();
            buffer.add(current.getDesc());
            if (parentId != null) {
                current = folderMap.get(parentId);
            } else {
                break;
            }
        }
        Collections.reverse(buffer);
        return String.join("/", buffer);
    }
1 Answers

First of all, your code looks fine. It compiles, it solves the problem, and it's probably not going to be a performance bottleneck (unless there are many folders). However, good for you for looking on ways to improve. BTW, there's a stack exchange site for that - codereview.stackexchange.com.

To improve the efficiency a bit, I'd pre-process the folders so I wouldn't have to iterate over the whole list every time to find the parent by its id. Just put the folders in a Map<Integer, Folder> (use the ID as key) so it'll be easy and quick to find the parent folder by id.

To improve readability, I'd also replace the recursion with a simple loop. It'll be easier on the eyes, more debuggable, and maybe even more performant.

Related